题解 CF708C 【Centroids】
LeavingZzz · · 题解
\mathsf{Solution\space For\space CF708C}
Upd:非常非常不好意思,这个屑贴错了代码,现在已经更新
被这个问题困扰到的欢迎私信D死这个屑
提供一种思想上和其他题解不一样(也许会更容易理解?)的解法
\mathsf{Description}
给出一棵树,你可以选择断掉其中的一条边将其重新连接到任意一个节点上,使其形成一棵新树,请问有多少个节点可以通过这种操作成为树的重心?
输出一行
\mathsf{Analysis}
重心给出的定义是所有的子树大小都小于等于
问题是,这个大小超出
而且这是一棵无根树,形态确定不了,现在所叙述的 “子树” 可能是其父亲节点,一切都似乎变得很麻烦....
但是现在如果我们事先就先找到一个重心作为根,似乎就会有一些美妙的性质。
如果一个节点
这就启发我们记录一个信息:对于一个节点
简化完一圈,就是要求所有节点除了本身以外的部分中不超出
设
同时
如果你这么写的话那你就太naive了(一转攻势
因为很明显
还有啥细节就看代码吧qaq
\mathsf{Code}
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=400007;
int N;
struct E{
int u,v;
}e[maxn<<1];
int first[maxn],nt[maxn<<1],ES;
inline void addE(int u,int v)
{
e[++ES]=(E){u,v};
nt[ES]=first[u];
first[u]=ES;
return ;
}
inline int R()
{
char c;
int re;
while((c=getchar())>'9'||c<'0');
re=c-48;
while((c=getchar())>='0'&&c<='9')
re=re*10+c-48;
return re;
}
int fa[maxn],sz[maxn];
int rt;//rt是找到的重心
void dfs1(int u)
{
int v;
sz[u]=1;
bool f=true;
for(int i=first[u];i;i=nt[i])
{
v=e[i].v;
if(v==fa[u]) continue;
fa[v]=u;
dfs1(v);
sz[u]+=sz[v];
if(sz[v]>N/2) f=false;
}
if(N-sz[u]>N/2) f=false;
if(f) rt=u;
return ;
}
int Max[maxn][2];//子树u中size最大的/次大的子树大小
void dfs2(int u)
{
int v;
sz[u]=1;
for(int i=first[u];i;i=nt[i])
{
v=e[i].v;
if(v==fa[u]) continue;
fa[v]=u;
dfs2(v);
sz[u]+=sz[v];
if(sz[v]>N/2) continue;//排除掉大于N/2的
if(sz[v]>Max[u][0]) Max[u][1]=Max[u][0],Max[u][0]=sz[v];
else if(sz[v]>Max[u][1]) Max[u][1]=sz[v];
}
return ;
}
int cut[maxn];
bool ans[maxn];
void dfs3(int u,int maxx)
{
int v;
cut[u]=maxx;
for(int i=first[u];i;i=nt[i])
{
v=e[i].v;
if(v==fa[u]) continue;
if(N-sz[u]<=N/2) maxx=max(maxx,N-sz[u]);//也许父亲的部分能直接构成子树
if(Max[u][0]==sz[v]) dfs3(v,max(maxx,Max[u][1]));//如果v即为最大的子树那么要用次大值
else dfs3(v,max(maxx,Max[u][0]));
}
if(N-sz[u]-cut[u]<=N/2||u==rt) ans[u]=true;
return ;
}
int main()
{
N=R();
int u,v;
for(int i=1;i<N;i++)
{
u=R();v=R();
addE(u,v);
addE(v,u);
}
dfs1(1);
fa[rt]=0;//注意清空fa
dfs2(rt);
dfs3(rt,0);
for(int i=1;i<=N;i++)
if(ans[i]) putchar('1'),putchar(32);
else putchar('0'),putchar(32);
return 0;
}
谢谢管理大大审核^_^