【题解】
就是基环外向树森林找环,然后从环向外统计size就可以了。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #define LL long long 6 #define rg register 7 #define N 200010 8 using namespace std; 9 int n,color,top,to[N],siz[N],st[N],pos[N]; 10 bool v[N],c[N]; 11 vector<int>from[N]; 12 inline int read(){ 13 int k=0,f=1; char c=getchar(); 14 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 15 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 16 return k*f; 17 } 18 void calc(int x){ 19 v[x]=1; 20 for(rg int i=0;i<from[x].size();i++)if(!siz[from[x][i]]){ 21 siz[from[x][i]]=siz[x]+1; calc(from[x][i]); 22 } 23 } 24 void dfs(int x){ 25 v[x]=1; st[pos[x]=++top]=x; 26 if(pos[to[x]]){ 27 int Size=top-pos[to[x]]+1; 28 for(rg int i=pos[to[x]];i<=top;i++) siz[st[i]]=Size,c[st[i]]=1; 29 for(rg int i=pos[to[x]];i<=top;i++) calc(st[i]); 30 // printf("%d %d ",to[x],x); 31 top=pos[to[x]]--; 32 } 33 else dfs(to[x]); 34 top--; pos[x]=0; 35 } 36 int main(){ 37 n=read(); 38 for(rg int i=1;i<=n;i++) to[i]=read(),from[to[i]].push_back(i); 39 // for(rg int i=1;i<=n;i++){ 40 // for(rg int j=0;j<from[i].size();j++) printf("%d ",from[i][j]); puts(""); 41 // } 42 for(rg int i=1;i<=n;i++) if(!v[i]) dfs(i); 43 for(rg int i=1;i<=n;i++) printf("%d ",siz[i]); 44 return 0; 45 }