灾难

搞出灭绝树。
一群动物的祖先就是他们的灭绝祖先
倍增搞lca

// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int M=110000;
int n,m,r[M],id[M],dep[M],f[M][21],tmp[M],cnt,ans[M];
vector <int> v[M],e[M];queue <int> q;
int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=20;i>=0;i--) if(f[x][i]&&dep[f[x][i]]>=dep[y]) x=f[x][i];
    for(int i=20;i>=0;i--) if(f[x][i]&&f[y][i]&&f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return x==y?x:f[x][0];
}
int main(){
    scanf("%d",&n);
    for(int i=1,x;i<=n;i++) 
        while(scanf("%d",&x)&&x) e[i].push_back(x),v[x].push_back(i),r[i]++;
    for(int i=1;i<=n;i++)if(!r[i]) q.push(i);
    for(;!q.empty();){int x=q.front();q.pop();tmp[++cnt]=x;
        for(int j=0;j<v[x].size();j++)
        if(!(--r[v[x][j]])) q.push(v[x][j]);
    }memset(r,0,sizeof r);dep[n+1]=1;
    for(int i=1,j,LCA,x;i<=n;i++){;
        if(!e[x=tmp[i]].size()){f[x][0]=n+1;dep[x]=2;continue;}
        for(j=1,LCA=e[x][0];j<e[x].size();j++)LCA=lca(LCA,e[x][j]);
        f[x][0]=LCA;r[LCA]++;dep[x]=dep[LCA]+1;
        for(j=0;f[x][j];f[x][j+1]=f[f[x][j]][j],j++);
    }
    while(!q.empty()) q.pop();
    for(int i=1;i<=n;ans[i]=1,i++)if(!r[i]) q.push(i);
    for(;!q.empty();){int x=q.front();q.pop();
        ans[f[x][0]]+=ans[x];
        if(!(--r[f[x][0]])) q.push(f[x][0]);
    }
    for(int i=1;i<=n;i++) printf("%d\n",ans[i]-1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值