[ZJOI]2012灾难

[文章目录]

Description

阿米巴是小强的好朋友。 阿米巴和小强在草原上捉蚂蚱。小强突然想,如果蚂蚱被他们捉灭绝 了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引 发一系列的生态灾难。 学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统。如果蚂 蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发 重大的灾难。 我们现在从专业一点的角度来看这个问题。我们用一种叫做食物网的 有向图来描述生物之间的关系:一个食物网有 n 个点,代表 n 种生物,如 果生物 x 可以吃生物 y,那么从 y 向 x 连一个有向边。这个图没有环。 图中有一些点没有连出边,这些点代表的生物都是生产者,可以通过光 合作用来生存;而有连出边的点代表的都是消费者,它们必须通过吃其他生 物来生存。如果某个消费者的所有食物都灭绝了,它会跟着灭绝。 我们定义一个生物在食物网中的“灾难值”为,如果它突然灭绝,那么 会跟着一起灭绝的生物的种数。 给定一个食物网,你要求出每个生物的灾难值

首先进行拓扑,把每个人的食物和自己的顺序找出来,然后建一个灾难树,每个节点要连的点为该节点所有的食物在灾难树上的lca。动态维护倍增lca。把食物向吃的人连边。
再树形DP求子树大小就好了。
借鉴黄学长的神奇lca%%%

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define N 76000
#define M 2001000
using namespace std;
int n,head[N],to[M],nxt[M],cnt;
int rd[N];int bin[30],tur[N],tot1,f[N];
queue<int> q;
bool inq[N];
int headt[N],tot[M],nxtt[M],cntt,deep[N],fa[N][30],ans[N];
void add(int x,int y)
{
    to[++cnt]=y;
    nxt[cnt]=head[x];
    head[x]=cnt;
}
void addt(int x,int y)
{
    int i;
    if(x==-1) x=0;
    tot[++cntt]=y;
    nxtt[cntt]=headt[x];
    headt[x]=cntt;
    deep[y]=deep[x]+1;
    fa[y][0]=x;
    for(i=1;i<=19;i++)
        fa[y][i]=fa[fa[y][i-1]][i-1];
}
void bin_ready()
{
    int i; bin[0]=1;
    for(i=1;i<=19;i++)
        bin[i]=bin[i-1]<<1;
}
int lca(int x,int y)
{
    int i;
    if(deep[x]<deep[y]) swap(x,y);
    int t=deep[x]-deep[y];
    for(i=0;bin[i]<=t;i++)
        if(t&bin[i]) x=fa[x][i];
    if(x==y) return x;
    for(i=19;i>=0;i--)
        if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
void topsort()
{
    bin_ready();
    int i,t,j,y,x;
    for(i=1;i<=n;i++)
        if(rd[i]==0) q.push(i);
    while(q.size())
    {
        t=q.front(),q.pop();
        tur[++tot1]=t;
        for(j=head[t];j;j=nxt[j])
        {y=to[j];
            rd[y]--;
            if(rd[y]==0) q.push(y);
        }
    }
    for(i=1;i<=tot1;i++)
    {
        y=tur[i];
        addt(f[y],y);
        for(j=head[y];j;j=nxt[j])
        {
            x=to[j];
            if(f[x]==-1) f[x]=y;
            else f[x]=lca(f[x],y);
        }
    }
}
void dfs(int x)
{
    int i;
    for(i=headt[x];i;i=nxtt[i])
    {
        dfs(tot[i]);
        ans[x]+=(ans[tot[i]]+1);
    }
}
int main()
{
    memset(f,-1,sizeof(f));
    scanf("%d",&n);
    int j,i,x;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        while(x!=0)
        {
            add(x,i),rd[i]++;
            scanf("%d",&x);
        }
    }
    topsort();
    //for(i=1;i<=tot1;i++) printf("%d ",tur[i]);
    dfs(0);
    for(i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    return 0;
}
/*5
0
1 0 1 0 2 3 0 2 0*/

 

发表评论

邮箱地址不会被公开。 必填项已用*标注