poj1655 树的重心 树形dp

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

处理处每个节点的孩子有几个,和树的大小就好了。

#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 99999999
using namespace std;
const int MAXN = 20010;
struct node
{
        int to;
        int v;
        int next;
}edge[MAXN*2];
int p,len;
int num[MAXN];
int vis[MAXN],pre[MAXN],ind,n;
int siz[MAXN];//the size of the tree
int h[MAXN];//the maxnum of subtree
int way;
void add(int x,int y)
{
        edge[ind].to = y;
        edge[ind].next = pre[x];
        pre[x] = ind ++;
}
void dfs1(int rt)
{
        int i;
        vis[rt] = 1;
        siz[rt] = 1;
        for(i=pre[rt]; i!=-1; i=edge[i].next){
                int t = edge[i].to;
                if(!vis[t]){
                        dfs1(t);
                        siz[rt] += siz[t];
                        h[rt] = max(h[rt],siz[t]);
                }
        }
}
int main()
{
        #ifndef ONLINE_JUDGE
        freopen("data.txt","r",stdin);
        #endif
        int i,j,t;
        scanf("%d",&t);
        while(t--)
        {
                scanf("%d",&n);
                ind = 1;
                memset(pre,-1,sizeof(pre));
                for(i=1; i<n; i++){
                        int x,y;
                        scanf("%d%d",&x,&y);
                        add(x,y);
                        add(y,x);
                }
                memset(vis,0,sizeof(vis));
                memset(siz,0,sizeof(siz));
                memset(h,0,sizeof(h));
                dfs1(1);
                int ans = INF;
                int f;
                for(i=1; i<=n; i++){
                    int temp = max(h[i],n-siz[i]);
                    if(ans > temp){
                        ans = temp;
                        f = i;
                    }
                }
                //cout<<siz[1]<<endl;
                cout<<f<<" "<<ans<<endl;
        }
}

 

posted @ 2016-02-28 11:23  sweat123  阅读(220)  评论(0编辑  收藏  举报