小朋友崇拜圈【DFS】
题目描述
班里 N 个小朋友,每个人都有自己最崇拜的一个小朋友(也可以是自己)。
在一个游戏中,需要小朋友坐一个圈,每个小朋友都有自己最崇拜的小朋友在他的右手边。
求满足条件的圈最大多少人?
小朋友编号为 1,2,3,⋯N。
输入描述
输入第一行,一个整数 N(3<N<105)。
接下来一行 N 个整数,由空格分开。
输出描述
要求输出一个整数,表示满足条件的最大圈的人数。
输入输出样例
示例
输入
9
3 4 2 5 3 8 4 6 9
输出
4
样例解释
如下图所示,崇拜关系用箭头表示,红色表示不在圈中。
显然,最大圈是[2 4 5 3] 构成的圈。
思路:
这道题使用深度优先搜索来计算,先使用一个数组 book 来标记哪些小朋友被人崇拜,将不被人崇拜的小朋友排除,不进行深搜
如:1 和 7 不被人崇拜,所以 book[1]=0,book[7]=0。对已进行深搜的小朋友用数组 flag 标记。
对被人崇拜的且没深搜的小朋友进行深搜,传入三个参数 当前小朋友的序号、起点序号、长度,进行递归,递归终止条件是,当前
小朋友的序号等于起点,则是一个崇拜圈,就更新最长的长度。最后输出答案。
代码:
#include<bits/stdc++.h>
#define N 100009
using namespace std;
int sum; //保存最大圈人数
int vis[N]; //存放输入的数据
int book[N]; //标记是否被人崇拜
int flag[N]; //标记是否深搜过
void dfs(int m,int start,int l)
{ //当前小朋友的序号、起点序号、长度
if(vis[m]==start)
{ //到头了则更新最大圈人数
sum=max(sum,l);
return ;
}
flag[vis[m]]=1; //标记环中的人,防止再次被深搜
dfs(vis[m],start,l+1); //递归
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&vis[i]);
book[vis[i]]++; //标记是否有崇拜者
}
for(int i=1;i<=n;i++)
{
if(book[i]!=0&&flag[i]==0)
{ //如果有崇拜者且没被深搜过
flag[i]=1; //标记为深搜过
dfs(i,i,1);
}
}
printf("%d",sum);
return 0;
}