3170. 小朋友崇拜圈
题目链接
3170. 小朋友崇拜圈
班里 \(N\) 个小朋友,每个人都有自己最崇拜的一个小朋友(也可以是自己)。
在一个游戏中,需要小朋友坐一个圈,每个小朋友都有自己最崇拜的小朋友在他的右手边。
求满足条件的圈最大多少人?
小朋友编号为 \(1,2,3,…N\)。
输入格式
第一行,一个整数 \(N\)。
接下来一行 \(N\) 个整数,由空格分开。
输出格式
输出一个整数,表示满足条件的最大圈的人数。
数据范围
\(3<N<10^5\)
输入样例1:
9
3 4 2 5 3 8 4 6 9
输出样例1:
4
样例1解释
如下图所示,崇拜关系用箭头表示,红色表示不在圈中。
显然,最大圈是 \([2 4 5 3]\) 构成的圈。
输入样例2:
30
22 28 16 6 27 21 30 1 29 10 9 14 24 11 7 2 8 5 26 4 12 3 25 18 20 19 23 17 13 15
输出样例2:
16
解题思路
dfs,有向图最大环数
将每个小朋友当作图上的节点,将每个节点连向他右边的小朋友,记录每个节点的入度,首先将那些入度为 \(0\) 的节点删除,因为这些节点一定不在环上,再遍历一遍那些入度不为 \(0\) 的节点,再dfs
一遍,直到到达起始点更新答案
- 时间复杂度:\(O(n)\)
代码
// %%%Skyqwq
#include <bits/stdc++.h>
#include <tr1/unordered_map>
#include <tr1/unordered_set>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
using namespace tr1;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
template <typename T>
void print(T x) {
if (x < 0) putchar('-'), x = -x;
if (x < 10) putchar(x + 48);
else print(x / 10), putchar(x % 10 + 48);
}
template <typename T>
void print(T x, char t) {
print(x); putchar(t);
}
const int N=1e5+5;
int n,in[N];
vector<int> adj[N];
int res=0;
bool v[N];
void dfs(int x,int cnt,int first)
{
for(int y:adj[x])
{
if(y==first)
{
res=max(res,cnt);
return ;
}
if(v[y]||!in[y])continue;
v[y]=true;
dfs(y,cnt+1,first);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
in[x]++;
adj[x].pb(i);
}
for(int i=1;i<=n;i++)
if(in[i]&&!v[i])
{
v[i]=true;
dfs(i,1,i);
}
cout<<res;
return 0;
}