poj 1655 树的重心
树的重心的一些性质
以下摘自百度
树的重心也叫树的质心。找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。
-
树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个距离和,他们的距离和一样。
-
把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
-
一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
-
一棵树最多有两个重心,且相邻。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define REP(i, a, b) for(register int i = (a); i < (b); i++) #define _for(i, a, b) for(register int i = (a); i <= (b); i++) using namespace std; const int MAXN = 1e5 + 10; struct Edge { int to, next; }; Edge e[MAXN << 1]; int head[MAXN], n, tot, ans; int dp[MAXN], num; inline void init() { memset(head, -1, sizeof(head)); tot = 0; } inline void AddEdge(int from, int to) { e[tot] = Edge{to, head[from]}; head[from] = tot++; } void read(int& x) { int f = 1; x = 0; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); } while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); } x *= f; } void dfs(int u, int fa) { dp[u] = 1; int maxt = 0; for(int i = head[u]; ~i; i = e[i].next) { int v = e[i].to; if(v == fa) continue; dfs(v, u); dp[u] += dp[v]; maxt = max(maxt, dp[v]); } maxt = max(maxt, n - dp[u]); if(maxt < num) num = maxt, ans = u; } int main() { int T; read(T); while(T--) { init(); read(n); REP(i, 1, n) { int u, v; read(u); read(v); AddEdge(u, v); AddEdge(v, u); } num = 1e9; dfs(1, -1); printf("%d %d\n", ans, num); } return 0; }