简单树形dp
给定一棵无向树,节点为n(n<=10000),问删除那些节点可以使得新图中的每一个连通分支的节点数都不超过n/2
首先 有dp维护以u为结点的下面的所以子树结点的个数
在每一个结点,同时找到他子节点的子树的结点数最大值
然后稍微判断一下就可以了;
///#include<bits/stdc++.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;
struct node
{
int u,v,w,next;
}ed[N<<2];
int vis[N],head[N],cnt=0,n;
void add(int u,int v)
{
ed[cnt].v=v;
ed[cnt].next=head[u];
head[u]=cnt++;
}
int dp[N],in[N],ou[N];
void init()
{
memset(head,-1,sizeof(head));
cnt=0;
memset(in,0,sizeof(in));
memset(ou,0,sizeof(ou));
//memset(dp,0,sizeof(dp));
}
vector<int>g;
void dfs(int u,int fa)
{
int mx=0;
for(int i=head[u];i!=-1;i=ed[i].next)
{
int v=ed[i].v;
if(v==fa)
continue;
dfs(v,u);
dp[u]+=dp[v];
mx=max(dp[v],mx);
}
if(n-dp[u]<=n/2&&mx<=n/2)
g.push_back(u);
}
int main()
{
scanf("%d",&n);
int u,v;
init();
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
in[v]++;
ou[u]++;
dp[i]=1;
}
dp[n]=1;
dfs(1,-1);
sort(g.begin(),g.end());
int len=g.size();
if(len)
{
for(int i=0;i<len;i++)
printf("%d\n",g[i]);
}
else
puts("NONE");
return 0;
}