题解:

构造灭绝树;

x指向的点表示x的祖先死亡则x死亡

动态LCA;

可以用LCT维护或直接更新倍增数组

最后统计子树点的个数

坑:

  我还不会序列型Toposort

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=100000; int n;
vector<int>G[maxn];
vector<int>G2[maxn]; int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
int addedge(int x,int y){
nex[++cntedge]=head[x];
to[cntedge]=y;
head[x]=cntedge;
} int f[maxn][20];
int depth[maxn];
int Lcainit(int i,int fa){
f[i][0]=fa;depth[i]=depth[fa]+1;
for(int j=1;j<=19;++j){
f[i][j]=f[f[i][j-1]][j-1];
}
} int Getlca(int x,int y){
if(depth[x]<depth[y])swap(x,y);
for(int j=19;j>=0;--j){
if(depth[f[x][j]]>=depth[y]){
x=f[x][j];
}
}
if(x==y)return x;
for(int j=19;j>=0;--j){
if(f[x][j]!=f[y][j]){
x=f[x][j];y=f[y][j];
}
}
return f[x][0];
} int root;
int indegree[maxn];
int sta[maxn],top;
int lca[maxn];
int Toposort(){
for(int i=1;i<=n;++i){
if(indegree[i]==0){
sta[++top]=i;
Lcainit(i,root);
G2[root].push_back(i);
}
}
while(top){
int x=sta[top--];
for(int i=head[x];i;i=nex[i]){
--indegree[to[i]];
if(indegree[to[i]]==0){
sta[++top]=to[i];
for(int j=0;j<G[to[i]].size();++j){
int v=G[to[i]][j];
if(lca[to[i]]==0){
lca[to[i]]=v;
}else{
lca[to[i]]=Getlca(lca[to[i]],v);
}
}
Lcainit(to[i],lca[to[i]]);
G2[lca[to[i]]].push_back(to[i]);
}
}
}
} int siz[maxn];
int dfs(int now,int fa){
siz[now]=1;
for(int i=0;i<G2[now].size();++i){
int v=G2[now][i];
if(v==fa)continue;
dfs(v,now);
siz[now]+=siz[v];
}
} void minit(){
for(int i=1;i<=n+1;++i){
G[i].clear();G2[i].clear();
}
cntedge=top=0;
memset(head,0,sizeof(head));
memset(f,0,sizeof(f));
memset(indegree,0,sizeof(indegree));
memset(lca,0,sizeof(lca));
}
int main(){
scanf("%d",&n);
minit();
root=n+1;depth[root]=1;
for(int i=1;i<=n;++i){
int x;
scanf("%d",&x);
while(x){
G[i].push_back(x);
addedge(x,i);
indegree[i]++;
scanf("%d",&x);
}
}
Toposort();
dfs(root,0);
for(int i=1;i<=n;++i)printf("%d\n",siz[i]-1);
return 0;
}

  

05-18 03:31