蓝桥杯小朋友崇拜圈(dfs)

这是一个关于图论的问题,目标是找到一个满足条件的最大圈,即每个孩子右边坐着他们崇拜的小孩。输入描述包含一个整数N(3<N<10^5)和N个整数表示崇拜关系,输出是满足条件的最大圈人数。提供的C++代码通过了所有测试用例,而Python代码只通过了75%。解决方案包括深度优先搜索(DFS)来寻找可能的圈并计算其数量。
摘要由CSDN通过智能技术生成

1. 问题描述:

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

输入描述

输入第一行,一个整数N(3 < N < 10 ^ 5)

接下来一行 N个整数,由空格分开。

输出描述

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

输入输出样例

示例

输入

9
3 4 2 5 3 8 4 6 9

输出

4

样例解释

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

运行限制
最大运行时间:1s
最大运行内存: 256M

来源:https://www.lanqiao.cn/problems/182/learning/

2. 思路分析:

分析题目可以知道我们可以搜索所有可能的圈(也可以使用模拟的思路进行求解),从当前起点i出发开始搜索,因为存在圈也就是存在环,所以在dfs搜索全部可能的圈的时候需要标记一下哪些位置是已经访问过的,并且在dfs方法中需要传递一开始的起点位置这样这样我们可以在递归过程中可以判断当前递归的位置是否等于了起始位置,如果相等说明就存在环了,因为还需要计算圈的数目,所以需要在递归的过程中维护一个变量,我们可以在递归方法中传递一个int类型的变量来记录圈的数目,但是不知道为什么在c语言网站上提交代码只是通过了75%的测试用例,不知道还有哪些情况是没有考虑到的

3. 代码如下:

from typing import List


class Solution:
    res = 1

    def solve(self, N: int, vis: List[int], nums: List[int]):
        for i in range(len(nums)):
            # 从当前的起点出发搜索可能的圈
            self.dfs(N, vis, nums, i, i, 0)
        return self.res

    def dfs(self, N: int, vis: List[int], nums: List[int], start: int, cur: int, count: int):
        if vis[cur] and cur == start:
            # 存在一个圈
            self.res = max(self.res, count)
            return
        # 访问过了那么就直接返回了
        if vis[cur]: return
        vis[cur] = 1
        # 因为递归的时候是下表而在数组中对应的是从1开始的编号所以减1才是正确的
        self.dfs(N, vis, nums, start, nums[cur] - 1, count + 1)
        vis[cur] = 0


if __name__ == '__main__':
    # dfs搜索其实也可以使用模拟的方法解决, 看懂题目中的那个图就可以很好解决了
    N = int(input())
    nums = list(map(int, input().split()))
    # 标记数组用来标记递归过程中访问过的位置
    vis = [0] * N
    print(Solution().solve(N, vis, nums))

一个类似的思路但是使用c++通过了的代码:

#include <iostream>
#include<cstring>
#include<math.h>
using namespace std;

int stuMap[100000];
int MAX = 0;
int vis[100000];
int cnt = 0;
void dfs(int i, int ori)
{
    if(vis[i] && i!=ori)
        return;
    if(vis[i] && i==ori)
    {
        MAX = fmax(MAX, cnt);
        return;
    }
    ++cnt;
    vis[i] = 1;
    dfs(stuMap[i], ori);
    vis[i] = 0;
    --cnt;
}

int main()
{
    int N;
    cin >> N;
    for (int i = 1; i <= N; ++i)
        cin >> stuMap[i];
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= N;++i)
        dfs(i,i);
    cout << MAX << endl;
    return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值