sgu 134 Centroid 树的重心

来源:互联网 发布:steam无法连接到网络 编辑:程序博客网 时间:2024/06/06 02:35

      对于一棵树,定义点k,删掉点k后,产生的几个联通量中节点数最大值 最小时,k为树的重心。遍历一边,用两个数组,size[i]表示i和i的子树中的节点数之和,sonsize[i]表示节点最多的子树的节点数,(n-size[i]就是这个节点没有枚举到的那个分支的节点数),然后枚举各个节点就可以了。

     

#include <iostream>#include <cstdio>#include <algorithm>#include <memory.h>#include <cmath>#include <string>#include <cstring>#include <vector>using namespace std;typedef long long ll;const int maxn=21000;int n,m;int ans,num;int p,q,k;vector<int> g[maxn];int size[maxn],sonsize[maxn];int dfs(int i,int fa){    size[i]=1;    for (int j=0; j<g[i].size(); j++)    {        if (fa!=g[i][j])        {            int v=g[i][j];            dfs(v,i);            size[i]+=size[v];            sonsize[i]=max(sonsize[i],size[v]);        }    }}int main(){//    freopen("in.txt","r",stdin);    scanf("%d",&n);    for (int i=1; i<=n; i++) g[i].clear();    memset(size,0,sizeof size);    memset(sonsize,0,sizeof sonsize);    int x,y;    for (int i=1; i<n; i++)    {      scanf("%d%d",&x,&y);      g[x].push_back(y);      g[y].push_back(x);    }    dfs(1,-1);    vector<int> out;    int minn=(1<<28);    for (int i=1; i<=n; i++)    {        minn=min(minn,max(n-size[i],sonsize[i]));    }    for (int i=1; i<=n; i++)    if (max(n-size[i],sonsize[i])==minn)    out.push_back(i);    cout<<minn<<" "<<out.size()<<endl;    cout<<out[0];    for (int i=1; i<out.size(); i++)    cout<<" "<<out[i]<<endl;    return 0;}


原创粉丝点击