求树的重心 poj 1655

题目链接:https://vjudge.net/problem/POJ-1655

这个就是找树的重心,树的重心就是树里面找一个点,使得以这个点为树根的所有的子树中最大的子树节点数最小。题目应该讲的比较清楚了,直接看代码吧:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque> 
using namespace std;
typedef long long LL;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 200005
struct node{
    int v,next;
}edge[maxn*2]; 
int n,m,k,t,cnt;
int vis[maxn],head[maxn],dis[maxn];//dis[i]记录以点i为树根的树,它子树里面包含点最多的值 
void init(){
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    cnt=0;
}
void add(int u,int v){
    edge[++cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
}
int DFS(int u){//搜索以点u为根节点的树下面的所有节点数量(包括自己)并返回,同时求出dis[u] 
    vis[u]=true;
    int sum_son=0;//一开始儿子节点总数为0 
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].v;
        if(!vis[v]){
            int s=DFS(v);// 
            sum_son+=s;//加上以v为根节点的子树的数量 
            dis[u]=max(dis[u],s);//求最大值 
        }
    }
    dis[u]=max(dis[u],n-sum_son-1);//不在这棵树下面的所有非子树节点的数量,总数-儿子节点数-自己 
    return sum_son+1;
}
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        init();
        int u,v,w;
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        DFS(1);
        int ans,max1=INF;
        for(int i=1;i<=n;i++){
            if(dis[i]<max1||dis[i]==max1&&i<ans){
                ans=i;
                max1=dis[i];
            }
        }
        printf("%d %d
",ans,max1);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/6262369sss/p/10021275.html