/*
* poj2378 AC
* 一次水过。
* 简单的树状DP,先做一次dfs算出每个结点的子孙结点总数,包括自己,sum[i]。
* 再做dfs计算删去每个结点x是否满足条件,即满足:
* 1) 每个结点的所有子结点i的sum[i]是否小于half。
* 2) 父结点方向上的结点总数,sum[1]-sum[x]是否小于half(1为树的根结点)。
* 若满足则为一个解,同时计算每个子结点是否满足。
* 若某结点不满足条件2,那么其子结点一定不满足条件,
* 因为sum[1]-sum[x]只会递增,而使子结点一定不满足条件2。
*
* */
#include<cstdio>
#include<algorithm>
#include<memory.h>
#define N 10010
using namespace std;
int tree[N<<1],head[N<<1],next[N<<1],sum[N+5];
int ans[N],len = 0,half;
bool vis[N];
long dfs_count(int x)
{
int i;
sum[x] = 1,vis[x] = true;
for(i=head[x];i;i=next[i])
if(!vis[tree[i]]) sum[x] += dfs_count(tree[i]);
return sum[x];
}
bool dfs_dp(int x)
{
vis[x] = true;
if(sum[1]-sum[x]>half) return false;
int i,flag = true;
for(i=head[x];i;i=next[i])
if(!vis[tree[i]])
{
if(dfs_dp(tree[i])) ans[++len] = tree[i];
if(sum[tree[i]]>half) flag = false;
}
return flag;
}
int main()
{
int n,tot,i,j,k;
// FILE* fin;
// fin = fopen("d.in","r");
scanf("%d",&n);
// fscanf(fin,"%d",&n);
for(half=n>>1,tot=0,i=1;i<=n-1;i++) {
// fscanf(fin,"%d%d",&j,&k);
scanf("%d%d",&j,&k);
tree[++tot] = k,next[tot] = head[j],head[j] = tot;
tree[++tot] = j,next[tot] = head[k],head[k] = tot;
}
memset(sum,0,sizeof(sum));
memset(vis,false,sizeof(vis));
dfs_count(1);
memset(vis,false,sizeof(vis));
if(dfs_dp(1)) ans[++len] = 1;
if(len==0)
{
printf("NONE\n");
return 0;
}
sort(ans+1,ans+len+1);
for(i=1;i<=len;i++)
printf("%d\n",ans[i]);
// fclose(fin);
return 0;
}
poj2378 Tree Cutting
最新推荐文章于 2020-06-20 15:42:00 发布