问题描述:
解题思路:
以每个小朋友为起点做dfs,dfs内如果碰到dfn(时间戳:记录目前是第几步,如第一个就是第一步),即该处已经走过,会形成一个环,就停下,判断是否大于mindfn(最小时间戳:每一个环末尾后一个(即一个新的环的开始),如果大于就用该步的dfn减去下一步dfn再加一。
图解:
以第五步为例,当走到5时,下一步为3,该点已经走过,则用5的dfn减下一步的dfn(即3的dfn) 再加一得该环的元素个数。再更新最小时间戳到新开始(即6)。
题解:
#include <iostream>
using namespace std;
const int N = 1e5 + 9;
int a[N];
int dfn[N], mindfn,idx, n;
int dfs(int i){ // 该dfs的含义是,以i元素为起点,深度搜索该元素。所以i需要从1开始到n
dfn[i] = ++idx; // 注意是先用后加,即++x
if(dfn[a[i]] != 0){
if(dfn[a[i]] >= mindfn)return dfn[i] - dfn[a[i]] + 1; // 条件可以等于
return 0;
}
return dfs(a[i]);
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i++)cin >> a[i];
int ans = 0;
for(int i = 1; i <= n; i++)
{
if(dfn[i] == 0) // 条件
{
mindfn = idx + 1;
ans = max(ans, dfs(i));
}
}
cout << ans <<'\n';
return 0;
}