砍树

 

题目描述

 给出一个树形图(“tree-shaped” network),有N个顶点。如果删除树上某一个顶点,整棵树就会分割成若干个部分。显然,每个部分内部仍保持连通性。

现在问:删除哪个点,使得分割开的每个连通子图中点的数量不超过N/2?如果有很多这样的点,就按升序输出。

输入

 第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

直接随机找到一个点往下搜索就行。如果一个节点的子儿子和他自己正好N/2个,他是,如果他及他的子儿子大于等于N/2,而且儿子中没有大于等于N/2的也是一个,只有这两种情况。

 1 #define MAXN 1000010UL
 2 
 3 #include<cstdio>
 4 #include<algorithm>
 5 //#include<vector>
 6 using namespace std;
 7 int n,head[MAXN],cnt,md;
 8 int ans[MAXN],ge,son[MAXN];
 9 bool vis[MAXN];
10 struct Node{
11     int en,to;
12 }eda[MAXN<<1];
13 void Add(int x,int y){
14     eda[++cnt].en=y;
15     eda[cnt].to=head[x];
16     head[x]=cnt;
17 }
18 void dfs(int x){
19     vis[x]=1;
20     bool flag=0;
21     bool er=0;
22     son[x]++;
23     for(int i=head[x];i;i=eda[i].to){
24         int y=eda[i].en;
25         if(!vis[y]){
26             dfs(y);
27             if(son[y]>=md){
28                 flag=1;
29                 if(son[y]==md) er=1; 
30             }
31             son[x]+=son[y];
32         }
33     }
34     if(!flag&&son[x]>=md){
35         ans[++ge]=x;
36     }
37     if(flag){
38         if(er){
39             ans[++ge]=x;
40         }
41     }
42 }
43 int main(){
44     freopen("tree.in","r",stdin);
45     freopen("tree.out","w",stdout);
46     scanf("%d",&n);
47     md=n>>1;
48     int x,y;
49     for(int i=1;i<n;i++){
50         scanf("%d%d",&x,&y);
51         Add(x,y);
52         Add(y,x);
53     }
54     dfs(1);
55     if(ge==0){
56         printf("NONE");
57         return 0;
58     }
59     sort(ans+1,ans+ge+1);
60     for(int i=1;i<=ge;i++){
61         if(ans[i]!=ans[i-1]) 
62             printf("%d\n",ans[i]);
63     }
64 }
View Code

 

posted @ 2015-10-11 18:28  Lenicodes  阅读(261)  评论(0编辑  收藏  举报