您的位置:首页 > 其它

SGU 134 Centroid(树形DP)

2016-04-15 11:37 344 查看
Description

给出一棵n个节点的无向树,问删去树上哪个顶点及与这个点相连的边后,能够最小化剩余连通块中节点的最大值

Input

第一行为一整数n表示点数,之后n-1行每行两个整数表示树上一条边(1<=n<=16000)

Output

输出删去一个顶点后最小的剩余剩余连通块中节点的最大值,并输出满足这个条件的节点数以及这些节点的编号

Sample Input

7

1 2

2 3

2 4

1 5

5 6

6 7

Sample Output

3 1

1

Solution

用树形DP统计以每个点为根的子树的节点数size[i]和每个点的子树中节点数最大值val[i],那么删去每个点后的答案值为val[i]=max(val[i],n-size[i]),之后从val数组中找最小值和最小值对应的i即可

Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 22222
struct Edge
{
int to,next;
}edge[2*maxn];
int n,head[maxn],tot,size[maxn],val[maxn],ans[maxn],res;
void init()
{
tot=res=0;
memset(head,-1,sizeof(head));
memset(val,0,sizeof(val));
}
void add(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void dfs(int u,int fa)
{
size[u]=1;
for(int i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa)continue;
dfs(v,u);
size[u]+=size[v];
val[u]=max(val[u],size[v]);
}
}
int main()
{
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dfs(1,0);
int m=n;
for(int i=1;i<=n;i++)
{
val[i]=max(val[i],n-size[i]);
if(val[i]<m)
m=val[i],res=0,ans[res++]=i;
else if(val[i]==m)ans[res++]=i;
}
printf("%d %d\n",m,res);
for(int i=0;i<res;i++)
printf("%d%c",ans[i],i==res-1?'\n':' ');
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: