小朋友崇拜圈(巧妙递归)

小朋友崇拜圈

班里N个小朋友,每个人都有自己最崇拜的一个小朋友(也可以是自己)。
在一个游戏中,需要小朋友坐一个圈,
每个小朋友都有自己最崇拜的小朋友在他的右手边。
求满足条件的圈最大多少人?

小朋友编号为1,2,3,…N
输入第一行,一个整数N(3<N<100000)
接下来一行N个整数,由空格分开。

要求输出一个整数,表示满足条件的最大圈的人数。

例如:
输入:
9
1 2 3 4 5 6 7 8 9
3 4 2 5 3 8 4 6 9

则程序应该输出:
4

解释:
如图p1.png所示,崇拜关系用箭头表示,红色表示不在圈中。
显然,最大圈是[2 4 5 3] 构成的圈

再例如:
输入:
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

程序应该输出:
16

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

一开始就直接想到并查集,但是因没有办法避免重复而超时,后来看了大佬的代码,就感觉还是自己太笨T.T


2年后有感:阿这,又看了一下代码,当初的注释确实有点问题,这个题的思路应该是递归找出所有圈,维护圈的最大长度,之前评论有兄弟指出来了,还没有细看代码,我的锅~

#include<iostream>
#include<vector>
using namespace std;
#define N 100005
int a[N];
int num[N];
int vis[N];
int n,ans,cnt;
int dfs(int x,int res)
{
	vis[x]=res;        //对应每个圈的起点
	num[x]=++cnt;      //每个数对应一个编号,用来计算圈的长度
	int y=a[x];        //y为x崇拜的人
	if(vis[y]==res)    //若y崇拜的人已经访问过且是当前这个圈内的人(vis值相同的所有值具有关联性,如果构成圈,在同一个圈内)
	{
		ans=max(ans,num[x]-num[y]+1);      //更新最大圈的长度
	}
	else
		dfs(y,res);        //递归继续向下找
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	{
		if(!vis[i])      //若数字在之前的圈没出现过,递归进入新圈
			dfs(i,i);
	}
	cout<<ans<<endl;
	return 0;
}
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值