题目链接:http://poj.org/problem?id=3107
题目大意:求树的重心,如果有多个节点,按节点编号升序输出所有的。
分析:用vector存储图会TLE,这里用了前向星存储图,用set来记录节点可以省去排序(set是一颗二叉树,自动把加入的点按升序排列了)。
实现代码如下:
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <set> using namespace std; const int maxn=50005; struct note { int v,next; }edge[maxn*2]; int head[maxn],ip; int maxx,n,num[maxn]; set <int> point; void init() { memset(head,-1,sizeof(head)); ip=0; } void addedge(int u,int v) { edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++; } void dfs(int u,int pre) { int tmp=-0x3f3f3f3f; num[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==pre)continue; dfs(v,u); num[u]+=num[v]; tmp=max(tmp,num[v]); } tmp=max(tmp,n-num[u]); if(tmp<=maxx) { if(tmp<maxx) { point.clear(); point.insert(u); maxx=tmp; } else if(tmp==maxx) point.insert(u); } } int main() { while(scanf("%d",&n)!=-1) { init(); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } memset(num,0,sizeof(num)); maxx=0x3f3f3f3f; dfs(1,-1); set <int> ::iterator it; bool first=true; for(it=point.begin();it!=point.end();it++) { if(first) { printf("%d",*it); first=false; } else printf(" %d",*it); } printf("\n"); } return 0; }