Description
有个同学(编号为 1 到)正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为的同学的信息传递对象是编号为的同学。游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自己的生日时,游戏结束。请问该游戏一共可以进行几轮?
Input
输入共 2行。
第 1行包含1个正整数n,表示n个人
第 2 行包含n 个用空格隔开的正整数T1 ,T 2 ,……,Tn , 其中第i个整数Ti表示编号为i
的同学的信息传递对象是编号为 T i 的同学,Ti≤n 且 Ti≠i。
数据保证游戏一定会结束。
Output
输出共 1行,包含 1个整数,表示游戏一共可以进行多少轮。
Sample Input
5
2 4 2 3 1
Sample Output
3
Hint
【输入输出样例 1 说明】
游戏的流程如图所示。当进行完第 3 轮游戏后,4 号玩家会听到 2 号玩家告诉他自己的生日,所以答案为 3。当然,第 3 轮游戏后,2 号玩家、3 号玩家都能从自己的消息来源得知自己的生日,同样符合游戏结束的条件。
对于 30%的数据,n≤ 200;
对于 60%的数据,n ≤ 2500;
对于 100%的数据,n ≤ 200000。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MAXN=200010; int e[MAXN]; int stack[MAXN]; bool instack[MAXN]; int dfn[MAXN]; int low[MAXN]; int cnt=0,head=0,ans=MAXN; void tarjan(int u) { stack[++head]=u; instack[u]=true; low[u]=dfn[u]=++cnt; int v=e[u]; if (!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if (instack[v]) low[u]=min(low[u],dfn[v]); if (low[u]==dfn[u]) { int sum=0; while (u!=v) { v=stack[head--]; //v千万不要再定义呀TAT instack[v]=false; sum++; } if (sum<ans&& sum!=1) ans=sum; } } int main() { int n,x; cin>>n; for (int i=1;i<=n;i++) { cin>>x; e[i]=x; } memset(instack,false,sizeof(instack)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i); cout<<ans; return 0; }