POJ 1655.Balancing Act-树的重心(DFS) 模板(vector存图)

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 17497   Accepted: 7398

Description

Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the largest tree in the forest T created by deleting that node from T. 
For example, consider the tree: 

Deleting node 4 yields two trees whose member nodes are {5} and {1,2,3,6,7}. The larger of these two trees has five nodes, thus the balance of node 4 is five. Deleting node 1 yields a forest of three trees of equal size: {2,6}, {3,7}, and {4,5}. Each of these trees has two nodes, so the balance of node 1 is two. 

For each input tree, calculate the node that has the minimum balance. If multiple nodes have equal balance, output the one with the lowest number. 

Input

The first line of input contains a single integer t (1 <= t <= 20), the number of test cases. The first line of each test case contains an integer N (1 <= N <= 20,000), the number of congruence. The next N-1 lines each contains two space-separated node numbers that are the endpoints of an edge in the tree. No edge will be listed twice, and all edges will be listed.

Output

For each test case, print a line containing two integers, the number of the node with minimum balance and the balance of that node.

Sample Input

1
7
2 6
1 2
1 4
4 5
3 7
3 1

Sample Output

1 2

Source

 
 
 
 
题意就是找树的重心,然后通过树的重心的概念,找到树的重心,删掉之后子树是最平衡的。直接贴的模板。
 
代码:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<bitset>
 6 #include<cassert>
 7 #include<cctype>
 8 #include<cmath>
 9 #include<cstdlib>
10 #include<ctime>
11 #include<deque>
12 #include<iomanip>
13 #include<list>
14 #include<map>
15 #include<queue>
16 #include<set>
17 #include<stack>
18 #include<vector>
19 using namespace std;
20 typedef long long ll;
21 typedef long double ld;
22 typedef pair<int,int> pii;
23 
24 const double PI=acos(-1.0);
25 const double eps=1e-6;
26 const ll mod=1e9+7;
27 const int inf=0x3f3f3f3f;
28 const int maxn=1e5+10;
29 const int maxm=100+10;
30 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
31 
32 int n,father;
33 int siz[maxn];//siz保存每个节点的子树大小
34 bool vist[maxn];
35 int point=inf,minsum=-1;//minsum表示切掉重心后最大连通块的大小
36 vector<int>G[maxn];
37 
38 void DFS(int u,int x)//遍历到节点x,x的父亲是u
39 {
40     siz[x]=1;
41     bool flag=true;
42     for(int i=0;i<G[x].size();i++){
43         int v=G[x][i];
44         if(!vist[v]){
45             vist[v]=true;
46             DFS(x,v);//访问子节点。
47             siz[x]+=siz[v];//回溯计算本节点的siz
48             if(siz[v]>n/2) flag=false;//判断节点x是不是重心。
49         }
50     }
51     if(n-siz[x]>n/2) flag=false;//判断节点x是不是重心。
52     if(flag&&x<point) point=x,father=u;//这里写x<point是因为本题中要求节点编号最小的重心。
53 }
54 
55 void init()
56 {
57     memset(vist,false,sizeof(vist));
58     memset(siz,0,sizeof(siz));
59     minsum=-1;
60     point=inf;
61     for(int i=0;i<maxn;i++) G[i].clear();
62 }
63 
64 int main()
65 {
66     int t;
67     scanf("%d",&t);
68     while(t--){
69         scanf("%d",&n);
70         init();
71         for(int i=1;i<n;i++){
72             int u,v;
73             scanf("%d%d",&u,&v);
74             G[u].push_back(v);
75             G[v].push_back(u);
76         }
77         vist[1]=1;
78         DFS(-1,1);//任意选取节点作为根,根节点的父亲是-1。
79         for(int i=0;i<G[point].size();i++)
80             if(G[point][i]==father) minsum=max(minsum,n-siz[point]);
81             else minsum=max(minsum,siz[G[point][i]]);
82         printf("%d %d\n",point,minsum);
83     }
84     return 0;
85 }

猜你喜欢

转载自www.cnblogs.com/ZERO-/p/10305516.html