想办法把这些点搞成一棵树,然后答案就是以该点为根的子树的大小。怎么搞呢?
把这些点的拓扑序搞出来,然后依次进行处理:
①如果当前点只有一个父亲,那么直接挂在它的父亲上
②如果当前点不止一个父亲,那么对这些父亲求lca,然后挂到这个lca上。
一开始程序一直无法运行,后来才知道,vector虽然资瓷删除指定元素,但由于它是动态开点的,无法提前记录指定元素的位置(push_back后会发生改变)。因此还是乖乖用set,反正时间复杂度还是对的。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define pvi pair<vector<int>::iterator,int>
#define mkp make_pair
#define X first
#define Y second
#define LL long long
const int N=70005;
int n;vector<int>pre[N];
set<int>he[N];
int dep[N],dad[N][20],cs;
int q[N],cnt[N];
int sz[N];
int lca(int x,int y){
int t;
if(dep[x]<dep[y])swap(x,y);
per(t,cs,0)if(dep[dad[x][t]]>=dep[y])x=dad[x][t];
if(x==y)return x;
per(t,cs,0)if(dad[x][t]!=dad[y][t])x=dad[x][t],y=dad[y][t];
return dad[x][0];
}
void BFS(){
int Ft=0,Rr=1,u,v,fa,t;
vector<int>::iterator ii;
set<int>::iterator jj;
dep[n+1]=1;
for(q[0]=n+1;Ft<Rr;){
if((u=q[Ft++])<=n){
fa=*pre[u].begin();
for(ii=++pre[u].begin();ii!=pre[u].end();++ii)
fa=lca(*ii,fa);
for(ii=pre[u].begin();ii!=pre[u].end();++ii)
he[*ii].erase(he[*ii].lower_bound(u));
he[fa].insert(u);
dep[u]=dep[dad[u][0]=fa]+1;
for(t=1;v=dad[dad[u][t-1]][t-1];++t)
dad[u][t]=v,cs=max(cs,t);
}
for(jj=he[u].begin();jj!=he[u].end();++jj)if(!(--cnt[*jj]))
q[Rr++]=*jj;
}
}
void DFS(int x,int fa){
set<int>::iterator ii;sz[x]=1;
for(ii=he[x].begin();ii!=he[x].end();++ii){
DFS(*ii,x);sz[x]+=sz[*ii];
}
}/*
void write(){
puts("pre");
int i;
vector<int>::iterator ii;
set<int>::iterator jj;
rep(i,1,n){
for(ii=pre[i].begin();ii!=pre[i].end();++ii)
printf("%d ",*ii);
puts("");
}
puts("he");
rep(i,1,n){
for(jj=he[i].begin();jj!=he[i].end();++jj)
printf("%d ",*jj);
puts("");
}
puts("");
}*/
int main(){
int i,x;
scanf("%d",&n);
rep(i,1,n){
while(1){
scanf("%d",&x);
if(!x)break;
he[x].insert(i);
pre[i].push_back(x);
}
if(pre[i].empty()){
he[n+1].insert(i);
pre[i].push_back(n+1);
}
cnt[i]=pre[i].size();
}
// write();
BFS();DFS(n+1,0);
rep(i,1,n)printf("%d\n",sz[i]-1);
return 0;
}