您的位置:首页 > 其它

砍树

2015-10-11 18:28 190 查看
题目描述

给出一个树形图(“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的也是一个,只有这两种情况。

#define MAXN 1000010UL

#include<cstdio>
#include<algorithm>
//#include<vector>
using namespace std;
int n,head[MAXN],cnt,md;
int ans[MAXN],ge,son[MAXN];
bool vis[MAXN];
struct Node{
int en,to;
}eda[MAXN<<1];
void Add(int x,int y){
eda[++cnt].en=y;
eda[cnt].to=head[x];
head[x]=cnt;
}
void dfs(int x){
vis[x]=1;
bool flag=0;
bool er=0;
son[x]++;
for(int i=head[x];i;i=eda[i].to){
int y=eda[i].en;
if(!vis[y]){
dfs(y);
if(son[y]>=md){
flag=1;
if(son[y]==md) er=1;
}
son[x]+=son[y];
}
}
if(!flag&&son[x]>=md){
ans[++ge]=x;
}
if(flag){
if(er){
ans[++ge]=x;
}
}
}
int main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
scanf("%d",&n);
md=n>>1;
int x,y;
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
Add(x,y);
Add(y,x);
}
dfs(1);
if(ge==0){
printf("NONE");
return 0;
}
sort(ans+1,ans+ge+1);
for(int i=1;i<=ge;i++){
if(ans[i]!=ans[i-1])
printf("%d\n",ans[i]);
}
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: