[CF708C]Centroids

来源:互联网 发布:java bigdecimal 加1 编辑:程序博客网 时间:2024/05/29 04:51

708C:Centroids

题意简述

给你一棵n个结点的树,你有一次机会把一条边断掉然后在任意位置接上一条边,但要保证操作之后还是一棵树。
现在求每个点进行这种操作之后是否可能成为重心,即所有子树大小都不超过n2的点。

数据范围

1n4105

思路

考虑某一个结点x可能成为重心的条件。
注意到一个重要的性质,一个结点size>n2的孩子最多只有一个。
那么肯定是x的那个孩子的子树中有一条边被切了,并且两边sizen2
那么树形DP。
son[i]为结点isize最大的儿子。
f[i]为结点i的子树中,以某一节点为根的子树的sizen2的最大值。
pos[i]f[i]的取值在i的哪一个孩子的子树中。
se[i]为结点i的子树中,以某一节点为根的子树sizen2的次大值,要求和f[i]不能在i同一个孩子的子树中。
g[i]为结点i的非子树中(第一步往父亲走),以某一节点为根的子树的sizen2的最大值。
转移什么的看代码吧…
特别麻烦= =

代码

#include<cstdio>#include<cstring>#include<iostream>using namespace std;struct edge{    int s,t,next;}e[800010];int head[400010],cnt;void addedge(int s,int t){    e[cnt].s=s;e[cnt].t=t;e[cnt].next=head[s];head[s]=cnt++;    e[cnt].s=t;e[cnt].t=s;e[cnt].next=head[t];head[t]=cnt++;}int n,u,v,siz;int son[400010],size[400010],f[400010],se[400010],pos[400010],fa[400010],g[400010];bool ok[400010];void dfs(int node,int lastfa){    fa[node]=lastfa;    size[node]=1;    son[node]=0;    for (int i=head[node];i!=-1;i=e[i].next)        if (e[i].t!=lastfa)        {            dfs(e[i].t,node);            size[node]+=size[e[i].t];            if (size[e[i].t]>size[son[node]])                son[node]=e[i].t;            if (size[e[i].t]<=n/2)            {                if (size[e[i].t]>f[node])                {                    se[node]=f[node];                    f[node]=size[e[i].t];                    pos[node]=e[i].t;                }                else if (size[e[i].t]>se[node])                    se[node]=size[e[i].t];            }            else if (f[e[i].t]>f[node])            {                se[node]=f[node];                f[node]=f[e[i].t];                pos[node]=e[i].t;            }            else if (f[e[i].t]>se[node])                se[node]=f[e[i].t];        }    if (n-size[node]>size[son[node]])        son[node]=lastfa;}void dfs2(int node,int lastfa){    for (int i=head[node];i!=-1;i=e[i].next)        if (e[i].t!=lastfa)        {            if (n-size[e[i].t]<=n/2)                g[e[i].t]=max(g[e[i].t],n-size[e[i].t]);            g[e[i].t]=max(g[e[i].t],g[node]);            if (pos[node]==e[i].t)                g[e[i].t]=max(g[e[i].t],se[node]);            else                g[e[i].t]=max(g[e[i].t],f[node]);            dfs2(e[i].t,node);        }}int main(){    scanf("%d",&n);    memset(head,0xff,sizeof(head));    cnt=0;    for (int i=1;i<n;i++)    {        scanf("%d%d",&u,&v);        addedge(u,v);    }    dfs(1,1);    dfs2(1,1);    for (int i=1;i<=n;i++)        if (son[i]==fa[i])            ok[i]=(n-size[i]-g[i]<=n/2);        else            ok[i]=(size[son[i]]-f[i]<=n/2);    for (int i=1;i<=n;i++)        printf("%d ",ok[i]);    return 0;}
0 0