题目大意:给出一棵树,去掉一个点后,这棵树会变成一些联通的块。求去掉哪个点之后所形成的块的最大数目最小。
思路:树形DP的思路。通过一次深搜求出每个节点为根的子树的大小,然后去掉这个节点之后,这棵树就会变成这个节点的各个子树,还有剩下的部分,求一下这些块中数目的最大值,就是去掉这个点时的ans,然后更新总的ans。
这个题其实就是树的重心。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 20010
using namespace std;
int cases;
int points;
int head[MAX],total;
int next[MAX << 1],aim[MAX << 1];
int p_ans,ans;
inline void Initialize();
inline void Add(int x,int y);
int DFS(int x,int last);
int main()
{
for(cin >> cases;cases; --cases) {
scanf("%d",&points);
Initialize();
for(int x,y,i = 1;i < points; ++i) {
scanf("%d%d",&x,&y);
Add(x,y),Add(y,x);
}
DFS(1,0);
printf("%d %d\n",p_ans,ans);
}
return 0;
}
inline void Initialize()
{
ans = 0x7f7f7f7f,total = 0;
memset(head,0,sizeof(head));
}
inline void Add(int x,int y)
{
next[++total] = head[x];
aim[total] = y;
head[x] = total;
}
int DFS(int x,int last)
{
int max_size = 0,size = 1;
for(int i = head[x];i;i = next[i]) {
if(aim[i] == last) continue;
int temp = DFS(aim[i],x);
max_size = max(max_size,temp);
size += temp;
}
max_size = max(max_size,points - size);
if(max_size < ans)
ans = max_size,p_ans = x;
return size;
}原文地址:http://blog.csdn.net/jiangyuze831/article/details/39961465