【树的重心】treecut

题目描述
有一个NN个节点的无根树,各节点编号为1..N1..N,现在要求你删除其中的一个点,使分割开的连通块中节点个数都不超过原来的一半多。

输入格式
第一行:一个整数N(1≤N≤10,000)N(1≤N≤10,000)。    后面有N−1N−1行:每行两个整数 XX 和 YY,表示一个边连接的两个节点号。

输出格式
输出所有可能选择的点。如果有多个节点,按编号从小到大输出,每个一行。 如果找不到这样的点,输出一行:"NONE".

样例一
input

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

3
8 
样例说明
删除3号或8号节点,则分枝最多有5个节点

限制与约定
时间限制:1s1s
空间限制:256MB
T

这道题是树的重心裸题,是为树hs做准备的

思路就是搜索一遍,然后如果这个点的max(size【son】,n-size【now】)小于等于n>>1,那么它就是重心

复杂度O(n);

 1 #include<bits/stdc++.h>
 2 #define N 10011
 3 #define clear(a,val) memset(a,val,sizeof(a))
 4 using namespace std;
 5 int n,x,y,cnt=1,pp;
 6 int head[N],nxt[N*2],to[N*2],size[N],ans[N];
 7 inline void add(int u,int v)
 8     {nxt[cnt]=head[u],to[cnt]=v,head[u]=cnt++;}
 9 inline void initandbuild()
10 {
11     clear(head,-1);
12     scanf("%d",&n);
13     for(int i=1;i<n;i++)
14     {
15         scanf("%d%d",&x,&y);
16         add(x,y),add(y,x);
17     }
18 }
19 int dfs(int now,int fa)
20 {
21     size[now]=1;int ma=-1;
22     for(int i=head[now];i!=-1;i=nxt[i])
23     {
24         int t=to[i];
25         if(t==fa)continue;
26         size[now]+=dfs(t,now);
27         ma=max(ma,size[t]);
28     }
29     ma=max(ma,n-size[now]);
30     if(ma<=(n>>1))ans[++pp]=now;
31     return size[now];
32 }
33 int main()
34 {
35     initandbuild();
36     dfs(1,-1);
37     sort(ans+1,ans+pp+1);
38     for(int i=1;i<=pp;i++)
39         printf("%d\n",ans[i]);
40     if(!pp)puts("NONE");
41     return 0;
42 }

猜你喜欢

转载自www.cnblogs.com/Qin-Wei-Kai/p/10204366.html