思路:如果一个点的某个儿子或者祖先节点数大于n/2,那么就要执行操作,找到该枝能移除的最大的子树X(<=n/2),该枝节点总数-X<=n/2就是可以,否则不可以。向上向下维护一个节点能删去的最大子树。
//reference:YxuanwKeith
# include <bits/stdc++.h>
# define pb push_back
using namespace std;
const int maxn = 4e5+30;
vector<int>v[maxn];
int n, sons[maxn], mx_son[maxn], down[maxn], up[maxn];
void dfs(int cur, int pre)
{
sons[cur] = 1;
for(auto to : v[cur])
{
if(to == pre) continue;
dfs(to, cur);
sons[cur] += sons[to];
down[cur] = max(down[cur], (sons[to]>n/2)?down[to]:sons[to]);
mx_son[cur] = max(mx_son[cur], sons[to]);
}
}
void dfs2(int cur, int pre)
{
multiset<int>s;
for(auto to : v[cur])
{
if(to == pre) continue;
s.insert((sons[to]>n/2)?down[to]:sons[to]);
}
for(auto to : v[cur])
{
if(to == pre) continue;
if(n-sons[to] <= n/2) up[to] = max(up[to], n-sons[to]);
else
{
up[to] = max(up[to], up[cur]);
s.erase(s.find((sons[to]>n/2)?down[to]:sons[to]));
if(!s.empty()) up[to] = max(up[to], *s.rbegin());
s.insert((sons[to]>n/2)?down[to]:sons[to]);
}
dfs2(to, cur);
}
}
int main()
{
scanf("%d",&n);
for(int i=1; i<n; ++i)
{
int a, b;
scanf("%d%d",&a,&b);
v[a].pb(b), v[b].pb(a);
}
dfs(1, 0);
dfs2(1, 0);
for(int i=1; i<=n; ++i)
{
int ans = 1;
if(mx_son[i] > n/2) ans = mx_son[i]-down[i] <= n/2;
if(n - sons[i] > n/2) ans = n-sons[i]-up[i] <= n/2;
printf("%d ",ans);
}
return 0;
}