[agc008F]Black Radius

大佬的博客讲得很好我就不赘述啦,这里提供链接:https://www.cnblogs.com/yoyoball/p/9483816.html

我就放一波代码

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int INF=100000000;
char ch[200010];
int n,x,y;long long ans=0;
int _col[200010],all; 
int col1[200010];//col1为统计以i为根子树可选点个数 
int mx1[200010],mx2[200010],maxfa[200010];//maxfa为以i为根的点向上能延伸到的最大值 
int _down[200010];//当以点i为根时,半径的下界 
struct node{int y,nxt;
}g[400010];int h[200010],tot=0;
void dfs1(int x,int fa)
{
    if (_col[x]) col1[x]=1,_down[x]=0;
    else _down[x]=INF;
    for (int i=h[x];i;i=g[i].nxt)
    if (g[i].y!=fa)
    {
        dfs1(g[i].y,x);
        int cnt=mx1[g[i].y]+1;
        if (cnt>mx1[x]) mx2[x]=mx1[x],mx1[x]=cnt;
        else mx2[x]=max(mx2[x],cnt);
        if (col1[g[i].y]) col1[x]+=col1[g[i].y],_down[x]=min(_down[x],mx1[g[i].y]+1);
    }
}
void dfs2(int x,int fa)
{
    if (all-col1[x]) _down[x]=min(_down[x],maxfa[x]);
    if (fa) 
    {
        if (maxfa[x]-1<=mx1[x]&&(all-col1[x])) ans++;
        else if (maxfa[x]-1>=mx1[x]&&col1[x]) ans++; 
    }
    for (int i=h[x];i;i=g[i].nxt)
    if (g[i].y!=fa)
    {
        int cnt=(mx1[x]==mx1[g[i].y]+1)?mx2[x]:mx1[x];
        maxfa[g[i].y]=max(cnt+1,maxfa[x]+1);
        dfs2(g[i].y,x);
    }
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        g[++tot]=node{y,h[x]};h[x]=tot;
        g[++tot]=node{x,h[y]};h[y]=tot;
    }
    scanf("%s",ch+1);
    all=ans=0;
    for (int i=1;i<=n;i++) if (ch[i]=='1') _col[i]=1,all++;
    dfs1(1,0);
    dfs2(1,0);
    for (int i=1;i<=n;i++)
    {
        if (maxfa[i]>mx1[i]) mx2[i]=mx1[i],mx1[i]=maxfa[i];
        else mx2[i]=max(mx2[i],maxfa[i]);
        if (mx2[i]-_down[i]+1>0) ans+=mx2[i]-_down[i]+1;
    }
    cout<<ans;
}

 

posted @ 2018-08-16 17:25  _雨后阳光  阅读(252)  评论(0)    收藏  举报