1、http://poj.org/problem?id=2378
2、题目大意:
一棵树有n个结点,现在要删除某个结点,使得分成的部分结点数最多不超过n/2个,题目与poj 3107类似,只是求得问题不同
用一个cnt[]数组记录下每个点有多少个子节点
那么我们要求的删除根节点u后剩余部分的最大数就是要么是u的子树中的最大值,要么是除去以u为根的树外的剩余结点数dp[u]=max(max(cnt[v]),n-cnt[u]);
3、AC代码:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define N 20005 #define INF 20010 int v[N],next[N],head[N]; int tot,ans,res,n; int cnt[N]; int dp[N]; void add_edge(int a,int b) { v[tot]=b; next[tot]=head[a]; head[a]=tot++; } void dfs(int u,int fa) { cnt[u]=1; for(int i=head[u];i!=-1;i=next[i]) { int vv=v[i]; if(vv!=fa) { dfs(vv,u); cnt[u]+=cnt[vv]; ans=max(ans,cnt[vv]); } } dp[u]=max(ans,n-cnt[u]); res=min(res,dp[u]); } int main() { int a,b; scanf("%d",&n); memset(head,-1,sizeof(head)); memset(cnt,0,sizeof(cnt)); tot=0; for(int i=1;i<n;i++) { scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } ans=-INF; res=INF; dfs(1,0); if(res>n/2) printf("NONE\n"); else { for(int i=1;i<=n;i++) { if(dp[i]<=n/2) printf("%d\n",i); } } return 0; }