有 nn 个同学( 编号为 11 到 nn)正在玩一个信息传递的游戏。
在游戏里每人都有一个固定的信息传递对象,其中,编号为 nn 的同学的信息传递对象是编号为 T_iTi的同学。游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象( 注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象)。 当有人从别人口中得知自己的生日时, 游戏结束。 请问该游戏一共可以进行几轮?
输入格式
输入共 22 行。
第 11 行包含 11 个正整数 n(2 \le n \le 200000)n(2≤n≤200000),表示 nn 个人。
第 22 行包含 nn 个用空格隔开的正整数 T_1, T_2, \cdots, T_nT1,T2,⋯,Tn,其中第 ii 个整数 T_iTi 表示编号为 ii 的同学的信息传递对象是编号为 T_iTi 的同学, T_i \le nTi≤n 且 T_i \ne iTi≠i。数据保证游戏一定会结束。
对于50%的数据 n \le 2000n≤2000。
输出格式
输出共 11 行,包含 11 个整数,表示游戏一共可以进行多少轮。
样例输入
5 2 4 2 3 1
样例输出
3
//version1
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 200050;
int nex[maxn];
int visited[maxn];
int main()
{
ios::sync_with_stdio(false);
int n;
cin >> n;
for(int i = 0; i < n;)
cin >> nex[++i];
int step = 1;
int ans = 0x3f3f3f3f;
for(int i = 0; i < n;){
int cur = ++i;// 当前节点没有被访问过
int start = step;
while(visited[cur] == 0){
visited[cur] = step++;// 访问当前节点
if(visited[nex[cur]] == 0){// 若下一个节点也没被访问过
;
}
else{// 若下一个节点已经被访问过了
if(visited[nex[cur]] < start)// 若是这个节点不是是本次访问访问的, 就什么也不做
;
else{// 若是本次访问的, 就计算距离
ans = min(ans, visited[cur] - visited[nex[cur]] + 1);
}
}
cur = nex[cur];// 不管怎么样, 都要指向下一个节点
}
}
cout << ans << endl;
return 0;
}
/*这是在version1提交过之后, 简单修改version1得到的, 形式比较紧凑
起初看到这道题的时候, 只想到了用一个set之类的容器, 去维护每个人知道的生日,
但是想想数据范围和具体操作就感觉不行;
晚上睡觉没睡着, 突然想到了一点思路, 每个人只会告诉其他一个人,
把这个抽象为边后, 就能得到一个图, 这道题就是要求这个图最小的环有几个元素
样例: 5 -> 1 -> 3
^ |
|- 4 <-
把样例抽象, 大约是这样
后来发现, 这是NOI的一道题, 别人的思路是dfs,
我后来想了想, 我的代码也是dfs, 思路还是不清晰.
*/
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 200050;
int nex[maxn];
int visited[maxn];
int main()
{
ios::sync_with_stdio(false);
int n;
cin >> n;
for(int i = 0; i < n;)
cin >> nex[++i];
int step = 1;
int ans = 0x3f3f3f3f;
for(int i = 0; i < n;){
int cur = ++i;// 当前节点没有被访问过
int start = step;
while(visited[cur] == 0){
visited[cur] = step++;// 访问当前节点
if(visited[nex[cur]] != 0){// 如果next指向的节点已经被访问过
if(visited[nex[cur]] >= start){// 如果是这次访问的, 就说明, 形成环路了
ans = min(ans, visited[cur] - visited[nex[cur]] + 1);
}
}
cur = nex[cur];// 不过怎样, 都要把cur = next[cur]
}
}
cout << ans << endl;
return 0;
}