#POJ 3107 Godfather (树的重心)
作者:互联网
Godfather
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 11123 | Accepted: 3895 |
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 ai, bi 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
题目大意 : 求树的重心
思路 : 在一颗树上, 删去某个点后, 剩余的所有子树中, 最大的节点数X, 这个X最小的点, 即为树的重心, 一棵树可能有多个重心, 但是只需要一遍dfs就可以全部求出来了, 先任意找一个顶点当作根节点, 往下搜, 记录每个点的孩子数量, 并记录所有孩子的最大节点数, 一个点搜完后, 更新该点的最大节点数, 并更新所有节点的最大节点数的最小值, 最后遍历每个点, 若他的X 等于我们记录的最小值, 那么他就是树的重心, 本题需要链式前向星, 否则TLE, 不明白的话画一下样例的图,想想就会了
Accepted code
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define MEM(x, b) memset(x, b, sizeof(x))
#define lowbit(x) ((x) & (-x))
#define P2(x) ((x) * (x))
typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }
struct Edge
{
int v, next;
}e[MAXN << 1];
int head[MAXN], n, cnt;
int dp[MAXN], p[MAXN], min_ = INF;
bool vis[MAXN];
void add(int from, int to) {
e[++cnt].v = to;
e[cnt].next = head[from];
head[from] = cnt;
}
void dfs(int x) {
vis[x] = 1, dp[x] = 1;
int max_ = 0;
for (int i = head[x]; i != -1; i = e[i].next) {
int vi = e[i].v;
if (!vis[vi]) {
dfs(vi);
dp[x] += dp[vi]; // 每个点的孩子数量
Max(max_, dp[vi]); // 孩子中最大的节点数
}
}
p[x] = max(max_, n - dp[x]); // 删除每个点剩余的所有树的节点的最大值
Min(min_, p[x]); // 上述最小值
}
int main()
{
cin >> n; MEM(head, -1);
for (int i = 1; i < n; i++) {
int ui, vi;
sc("%d %d", &ui, &vi);
add(ui, vi); add(vi, ui);
}
dfs(1);
for (int i = 1; i <= n; i++) {
if (p[i] == min_) cout << i << " ";
}
cout << endl;
return 0;
}
标签:include,police,Godfather,3107,tree,POJ,mafia,节点 来源: https://blog.csdn.net/weixin_43851525/article/details/100125941