题目描述
每年,在威斯康星州,奶牛们都会穿上衣服,收集农夫约翰在N(1<=N<=100,000)个牛棚隔间中留下的糖果,以此来庆祝美国秋天的万圣节。
由于牛棚不太大,FJ通过指定奶牛必须遵循的穿越路线来确保奶牛的乐趣。为了实现这个让奶牛在牛棚里来回穿梭的方案,FJ在第i号隔间上张贴了一个“下一个隔间”Next_i(1<=Next_i<=N),告诉奶牛要去的下一个隔间;这样,为了收集它们的糖果,奶牛就会在牛棚里来回穿梭了。
FJ命令奶牛i应该从i号隔间开始收集糖果。如果一只奶牛回到某一个她已经去过的隔间,她就会停止收集糖果。
在被迫停止收集糖果之前,计算一下每头奶牛要前往的隔间数(包含起点)。
输入格式
第1行 整数n。
第2行到n+1行 每行包含一个整数 next_i 。
输出格式
n行,第i行包含一个整数,表示第i只奶牛要前往的隔间数。
输出样例
1
2
2
3
code
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int mxn=110000; struct Edge { int to,next; }edge[mxn]; bool ins[mxn]; int n,cnt,k,idx,top; int ans[mxn],val[mxn],bel[mxn],next[mxn]; int stk[mxn],low[mxn],dfn[mxn],first[mxn]; void add(int from,int to) { edge[++cnt].to=to; edge[cnt].next=first[from]; first[from]=cnt; } void Tarjan(int x) { dfn[x]=low[x]=++idx; stk[++top]=x; ins[x]=1; for(int i=first[x];i;i=edge[i].next) { int to=edge[i].to; if(!dfn[to]) { Tarjan(to); low[x]=min(low[x],low[to]); } else if(ins[to]) { low[x]=min(low[x],low[to]); } } if(low[x]==dfn[x]) { ++k; int curr,len=0; do{ ++len; curr=stk[top--]; bel[curr]=k; ins[curr]=0; }while(curr!=x); val[k]=len; } } void serch(int root,int x,int stp) { if(ans[x]!=0) ans[root]=ans[x]+stp; else serch(root,next[x],stp+1); } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&next[i]); add(i,next[i]); if(i==next[i]) ans[i]=1; } for(int i=1;i<=n;++i) if(!dfn[i]) Tarjan(i); for(int i=1;i<=n;++i) if(val[bel[i]]!=1) ans[i]=val[bel[i]]; for(int i=1;i<=n;++i) if(!ans[i]) serch(i,next[i],1); for(int i=1;i<=n;++i) { printf("%d\n",ans[i]); } return 0; }