1. 程式人生 > >HNIEOJ 3964: 砍樹

HNIEOJ 3964: 砍樹

pen pan 連通性 hide 解決 () lib 如果 http

3964: 砍樹

時間限制: 1 Sec 內存限制: 128 MB
提交: 16 解決: 4
[提交] [狀態] [討論版] [命題人:外部導入]

題目描述

給出一個樹形圖(“tree-shaped” network),有N個頂點。如果刪除樹上某一個頂點,整棵樹就會分割成若幹個部分。顯然,每個部分內部仍保持連通性。

現在問:刪除哪個點,使得分割開的每個連通子圖中點的數量不超過N/2?如果有很多這樣的點,就按升序輸出。
例如,如下圖所示的樹形圖,砍掉頂點3或者頂點8,分割開的各部分滿足條件。

輸入

第1行:1個整數N,表示頂點數。頂點編號1-N。 接下來n-1行每行兩個整數x,y,表示x到y有一條邊。

輸出

若幹行,每行1個整數,表示一個符合條件的頂點的編號。如果沒有頂點符合條件,則僅在第1行輸出“NONE”。

樣例輸入

10
1 2
2 3
3 4
4 5
6 7
7 8
8 9
9 10
3 8

樣例輸出

3
8

提示

【數據範圍及約定】

對於50%的數據,滿足1≤N≤10000

對於100%的數據,滿足1≤N≤1000000

來源/分類

數據結構-圖

分析

  1. 先構造無向圖,再dfs;
  2. dfs時使用有返回值模式,其返回值表示各子樹節點數目。
  3. 刪除的點滿足 以刪除點為根,各子樹節點數目不超n/2 且 祖先數目也不超過n/2
  4. 祖先數目=總節點數目-1-各子樹節點數目
代碼如下 技術分享圖片
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 1000000+4
typedef struct anode
{
    int adjvex;
    struct anode *nextarc;
}arcnode;
typedef struct
{
    arcnode *firstarc;
}vnode;
typedef struct
{
    vnode adjlist[maxn];
    
int n,e; }adjgraph; int visit[maxn],ans[maxn],n; int dfs(adjgraph *g,int v) { int max=0,h=0,flag=0; visit[v]++; arcnode *p=g->adjlist[v].firstarc; while(p!=NULL) { if(!visit[p->adjvex]) { int temp=dfs(g,p->adjvex); h+=temp;//所以孩子數目 max>temp? : max=temp; //從分枝中找出最大節點數 } p=p->nextarc; } ans[v]= max>n-1-h ? max:n-1-h; return h+1; } void link(adjgraph *&g,int a,int b) { arcnode *p1=g->adjlist[a-1].firstarc,*p; p=(arcnode *)malloc(sizeof(arcnode)); p->adjvex=b-1; p->nextarc=NULL; if(p1==NULL) g->adjlist[a-1].firstarc=p; else { p->nextarc=p1->nextarc; p1->nextarc=p; } } void destroy(adjgraph *&g) { arcnode *p; for(int i=0;i<g->n;i++) { p=g->adjlist[i].firstarc; while(p!=NULL) { arcnode *temp=p; p=p->nextarc; free(temp); } } free(g); } int main() { int i,flag1=1; adjgraph *g; g=(adjgraph *)malloc(sizeof(adjgraph)); scanf("%d",&n); g->n=n; for(i=0;i<n;i++) g->adjlist[i].firstarc=NULL; for(i=0;i<n-1;i++) { int a,b; scanf("%d%d",&a,&b); link(g,a,b); link(g,b,a); } /*for(i=0;i<n;i++) { arcnode *p; p=g->adjlist[i].firstarc; printf("%d->",i+1); while(p!=NULL) { printf("%d->",p->adjvex+1); p=p->nextarc; } printf("NULL\n"); }*/ dfs(g,0); int flag=0; for(i=0;i<n;i++) if(ans[i]<=(n>>1)) { printf("%d\n",i+1); flag=1; } if(!flag) printf("NONE\n"); destroy(g); return 0; }
View Code

HNIEOJ 3964: 砍樹