类比 computer,记录 dp1 最大,次大和最大时儿子节点。
同时定义 sid[i]:=最大节点的子树根节点下标。
DFS1——
考虑一棵树,根为x,遍历到儿子y,根为i的子树节点数为sze[i]。
- 若sze[y]<=n/2,直接取值都可以,不用管他,故此时 dp1 更新一下 sze[y] 即可。
- 若反之,取极限 dp1[y].最大值更新即可。
void DFS1(int x=1,int par=-1){
sze[x]=1;
for(auto i:G[x]){
int y=i;
if(y==par)continue;
DFS1(y,x);
sze[x]+=sze[y];
if(sze[y]>sze[sid[x]])sid[x]=y;
int ins=(sze[y]<=n/2?sze[y]:dp1[y].maxn);
if(dp1[x].maxn<ins){
dp1[x].maxx=dp1[x].maxn;
dp1[x].maxn=ins;
dp1[x].pos=y;
}
else if(dp1[x].maxx<ins)dp1[x].maxx=ins;
}
return;
}
DFS2——
dp2[x]:=当这个点不为Centriod时,可以平摊节点的最大化数量
解释一下吧:
if(sze[sid[x]]>n/2)out[x]=(sze[sid[x]]-dp1[x].maxn<=n/2);//如果均摊后能成功
else if(n-sze[x]>n/2)out[x]=(n-sze[x]-dp2[x]<=n/2);//同上,只不过变成了父亲部
for(auto i:G[x]){
int y=i;
if(y==par)continue;
dp2[y]=max(dp2[y],(n-sze[x]>n/2?dp2[x]:n-sze[x]));
if(dp1[x].pos==y)dp2[y]=max(dp2[y],dp1[x].maxx);
else dp2[y]=max(dp2[y],dp1[x].maxn);
DFS2(y,x);
}


被折叠的 条评论
为什么被折叠?



