CF708C Centroids

xyzfrozen Lv5

先考虑以 为根的情况

考虑到至多只有一个 的子树 ,我们肯定找是 中那个最大的 的子树 ,然后扣下来接到 上面,再判断能否成为重心,即

我们考虑如何维护这个过程,我们先维护最大的儿子 ,然后求每个 内最大的 的子树 ,记为

这样就把问题转化成

我们考虑换根解决剩下的部分,我们还需要维护 的补树中的 ,传给

  1. 此时显然为 中的次大子树 中的 ,所以这启示我们还需要维护一个次大的 的子树大小
  2. 此时显然为

记这个

并且上述的要和 取个最大值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include<bits/stdc++.h>
#define pt putchar(' ')
#define nl puts("")
#define pi pair<int,int>
#define pb push_back
#define go(it) for(auto &it:as[x])
using namespace std;

const int N=4e5+10;
int n,u,v;
int sz[N],f[N],g[N],h[N],son[N],bel[N],ans[N];
vector<int> as[N];

int fr(){
int x=0,flag=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
return x*flag;
}
void fw(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) fw(x/10);
putchar(x%10+'0');
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}

void prework(int x,int rt)
{
sz[x]=1;
go(v)
{
if(v==rt) continue;
prework(v,x);
sz[x]+=sz[v];
if(sz[son[x]]<sz[v]) son[x]=v;
int val=(sz[v]<=n/2)?sz[v]:f[v];
if(val>f[x]) g[x]=f[x],f[x]=val,bel[x]=v;
else g[x]=max(g[x],val);
}
}

void dfs(int x,int rt)
{
ans[x]=1;
if(n-sz[x]>n/2 && n-sz[x]-h[x]>n/2) ans[x]=0;
if(sz[son[x]]>n/2 && sz[son[x]]-f[son[x]]>n/2) ans[x]=0;

go(v)
{
if(v==rt) continue;
h[v]=(n-sz[x]<=n/2)?(n-sz[x]):h[x];

if(v==bel[x]) h[v]=max(h[v],g[x]); //最大子树
else h[v]=max(h[v],f[x]);
dfs(v,x);
}
}

int main()
{
n=fr();
for(int i=1;i<n;i++)
{
u=fr(),v=fr();
as[u].pb(v),as[v].pb(u);
}

prework(1,0);
dfs(1,0);
for(int i=1;i<=n;i++)
fw(ans[i]),pt;

return 0;
}
  • 标题: CF708C Centroids
  • 作者: xyzfrozen
  • 创建于 : 2023-10-10 23:55:14
  • 更新于 : 2026-06-06 06:22:05
  • 链接: https://xyzfrozen.github.io/xyzfrozen/CF708C-Centroids/CF708C-Centroids/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
CF708C Centroids