POJ.1655 Balancing Act (树形DP 树的重心)
标签(空格分隔): 动态规划
题意分析
给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的.
所谓树的重心,指的是:树上的某个节点,其所有子树中最大的子树节点数目最少,换句话说,删除个节点以后,最大联通块的节点数最少。
一张图解释一下
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define nmax 20010
using namespace std;
struct edge{
int to,next;
}edg[nmax*2];
int head[nmax],sz[nmax];
int tot = 0;
int id,ans;
int t,n;
void add(int u, int v){
edg[tot].to = v;
edg[tot].next = head[u];
head[u] = tot++;
}
void dfs(int rt, int fa){
sz[rt] = 1;
int tmp = 0;
for(int i = head[rt]; i!=-1 ;i = edg[i].next){
int nxt = edg[i].to;
if(nxt != fa){
dfs(nxt,rt);
sz[rt]+=sz[nxt];
tmp = max(tmp,sz[nxt]);
}
}
tmp = max(tmp,n-sz[rt]);
if(tmp < ans || (tmp == ans && rt < id )) {
id = rt;
ans = tmp;
}
}
void init(){
memset(head,-1,sizeof head);
ans = 1e9+7;
id = n+1;
tot = 0;
}
int main()
{
//freopen("im.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d",&n);
init();
for(int i = 0;i<n-1;++i){
int x,y;
scanf("%d %d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1,0);
printf("%d %d\n",id,ans);
}
return 0;
}