您的位置:首页 > 其它

poj3107 树形dp

2015-12-30 14:36 281 查看
  好久没更了。前段时间去ec-final,实力水一波,混了个铜,虽然很弱,但是可以算是对之前一段时间的回报吧。

现在每天忙着复习,逃课太多,啥都不会。。。不想挂科啊!!Orz...

  题意(简化):警察想抓捕黑手党老大。现在警察们认为黑手党内部是树形结构,每个人看做节点。删除一个节点,这棵树就分为几个连同分量。现在对于每个节点,删去后得到的连同分量的最大值为t。t的值最小的是哪些人,都输出。

  解法:对于节点,他的最大连同分量只可能来自2方面,他的孩子方向或者他的父亲方向。只要判断一下大小即可。

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
using namespace std;
const int MAXN = 50010;
struct node{
int to;
int next;
}edge[MAXN*3];
int index,vis[MAXN],pre[MAXN],n;
int num[MAXN],dp[MAXN],way[MAXN],ans[MAXN];
void add(int x,int y)
{
edge[index].to = y;
edge[index].next = pre[x];
pre[x] = index++;
}
void dfs1(int rt)
{
vis[rt] = 1;
int i;
for(i=pre[rt]; i!=-1; i=edge[i].next){
int v = edge[i].to;
if(!vis[v]){
dfs1(v);
if(dp[rt] < num[v]){
dp[rt] = num[v];
way[rt] = v;
}
num[rt] += num[v];
}
}
num[rt] += 1;
}
void dfs2(int rt,int pa)
{
vis[rt] = 1;
int i;
if(pa == -1){
for(i=pre[rt]; i!=-1; i=edge[i].next){
int v = edge[i].to;
if(!vis[v]){
ans[rt] =max(ans[rt], num[v]);
dfs2(v,rt);
}
}
}
else {
ans[rt] = n - num[rt];
for(i=pre[rt]; i!=-1; i=edge[i].next){
int v = edge[i].to;
if(!vis[v]){
ans[rt] = max(ans[rt], dp[rt]);
dfs2(v,rt);
}
}
}
}
int main()
{
int i,j;
while(~scanf("%d",&n))
{
index = 1;
memset(pre,-1,sizeof(pre));
for(i=1; i<n; i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
memset(dp,0,sizeof(dp));
memset(way,0,sizeof(way));
memset(num,0,sizeof(num));
memset(ans,0,sizeof(ans));
memset(vis,0,sizeof(vis));
dfs1(1);
memset(vis,0,sizeof(vis));
dfs2(1,-1);
int v = 9999999999;
for(i=1; i<=n; i++){
if(ans[i] != 0)
v = min(v,ans[i]);
}
int flag = 0;
for(i=1; i<=n; i++){
if(v == ans[i])
{
if(!flag){
printf("%d",i);
flag = 1;
}
else printf(" %d",i);
}
}
cout<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: