poj 3107 Godfather(树的重心)

Godfather

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 7885   Accepted: 2786

Description

Last years Chicago was full of gangster fights and strange murders. The chief of the police got really tired of all these crimes, and decided to arrest the mafia leaders.

Unfortunately, the structure of Chicago mafia is rather complicated. There are n persons known to be related to mafia. The police have traced their activity for some time, and know that some of them are communicating with each other. Based on the data collected, the chief of the police suggests that the mafia hierarchy can be represented as a tree. The head of the mafia, Godfather, is the root of the tree, and if some person is represented by a node in the tree, its direct subordinates are represented by the children of that node. For the purpose of conspiracy the gangsters only communicate with their direct subordinates and their direct master.

Unfortunately, though the police know gangsters’ communications, they do not know who is a master in any pair of communicating persons. Thus they only have an undirected tree of communications, and do not know who Godfather is.

Based on the idea that Godfather wants to have the most possible control over mafia, the chief of the police has made a suggestion that Godfather is such a person that after deleting it from the communications tree the size of the largest remaining connected component is as small as possible. Help the police to find all potential Godfathers and they will arrest them.

Input

The first line of the input file contains n — the number of persons suspected to belong to mafia (2 ≤ n ≤ 50 000). Let them be numbered from 1 to n.

The following n − 1 lines contain two integer numbers each. The pair aibi means that the gangster ai has communicated with the gangster bi. It is guaranteed that the gangsters’ communications form a tree.

Output

Print the numbers of all persons that are suspected to be Godfather. The numbers must be printed in the increasing order, separated by spaces.

Sample Input

6
1 2
2 3
2 5
3 4
3 6

Sample Output

2 3


分析

题目的意思很明确,就是求所有树的重心(再按字典序输出)。

那么我们先介绍一下树的重心。
树的重心定义为:
树中的一个点,删掉该点,使剩下的树所构成的森林中最大的子树节点数最少。
树的重心推论:
1.设树上的一个点S,树上其余所有点到S点的距离之和最小,那么S就是重心。
2.树的重心不唯一。
那么我们依靠定义来求树的重心好了。
首先我们确定一个根,进行一遍dfs,回溯的时候可以递归统计该点不同子树所拥有的点的数量,
然后再用(总节点数)减去(1)减去(子树),就是其父亲那边的那棵树的点的数量,
取min,最后求出即可。

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 const int MAXN = 50010;
 8 const int MAXM = 100010;
 9 
10 struct Edge{
11     int to,nxt;
12 }e[MAXM];
13 int head[MAXM],tot;
14 int son[MAXN];
15 int ans[MAXN],p,Ans = 1e9,n;
16 
17 inline int read() {
18     int x = 0,f = 1;char ch = getchar();
19     for (; ch<'0'||ch>'9'; ch = getchar())
20         if (ch=='-') f = -1;
21     for (; ch>='0'&&ch<='9'; ch = getchar())
22         x = x*10+ch-'0';
23     return x*f;
24 }
25 inline void init() {
26     memset(head,0,sizeof(head));
27     memset(son,0,sizeof(son));
28     tot = 0;
29 }
30 inline void add_edge(int u,int v) {
31     e[++tot].to = v,e[tot].nxt = head[u],head[u] = tot; 
32 }
33 void dfs(int u,int fa) {
34     int cnt = 0;
35     for (int i=head[u]; i; i=e[i].nxt) {
36         int v = e[i].to;
37         if (v==fa) continue;
38         dfs(v,u);
39         son[u] += son[v]+1;
40         cnt = max(cnt,son[v]+1);
41     }
42     cnt = max(cnt,n-son[u]-1);
43     if (cnt<Ans) {Ans = cnt,p = 0,ans[++p] = u;}
44     else if (cnt==Ans) {ans[++p] = u;}
45 }
46 int main() {
47     
48     while (scanf("%d",&n)!=EOF) {
49         init();
50         for (int u,v,i=1; i<n; ++i) {
51             u = read(),v = read();
52             add_edge(u,v),add_edge(v,u);
53         }
54         dfs(1,0);
55         sort(ans+1,ans+p+1);
56         for (int i=1; i<=p; ++i) 
57             printf("%d ",ans[i]);    
58         printf("
");    
59     }    
60     return 0;
61 }
原文地址:https://www.cnblogs.com/mjtcn/p/7898408.html