poj 1655 树的重心

树的重心的一些性质

以下摘自百度

树的重心也叫树的质心。找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。

  1. 树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个距离和,他们的距离和一样。
  2. 把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
  3. 一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
  4. 一棵树最多有两个重心,且相邻。
#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;
}

 

posted @ 2018-10-31 20:42  Sugewud  阅读(124)  评论(0编辑  收藏  举报