蓝桥杯:小朋友崇拜圈

题目描述

班里 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] 构成的圈。

分析:

        题目会拿到一个圈,我们可以用数组来存放圈,数组长度是N+1,这样我们就可以从下标1开始,到N,下标1就是第一个学生,这个位置存放的是第一个学生指向的下一个学生,也就是样例中的,第一个学生指向第三个学生,所以array[1] = 3;然后第二个学生也是类似。

        我们采用dfs来处理,首先我们从学生1开始,依次往下遍历他指向的下一个学生,他指向的下一个学生的下一个学生这样。但是题目给出的数据里面是存在环的(也就是不加结束条件的话会成为死循环),那么我们就需要处理环。

        处理环的话我考虑使用一个和学生数组一样长度的boolean数组,boolean数组的值只能是true和false,我们初始化boolean数组为false,当我们进入循环,就把当前下标对应的boolean数组的值修改为true,我们进入循环的判断就是判断当前下标的boolean数组是否为false,如果是false,代表这个下标还没有遍历过,可以继续进行遍历,如果遍历过了,那么就不再进行循环。

        遍历完成一遍之后,肯定会结束的(环的特性),我们只需要判断初始下标进的循环,出来循环的下标,这两个下标是否相同,如果相同,他们就完成了一次闭环,即这个下标可以构成一个环。如果不相同,那么就是里面存在环,但这个环不是从初始下标开始的。就继续往下找环的初始节点。

        因为不知道提供的数据里面有几个环,我们每找到一个环,都对最大圈数进行一次判断和更新。

Java:

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
  //记录环的最大圈数
  static int max = 0;
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //拿数据
        int n = scan.nextInt();
        //小朋友指向的朋友就放到i的下面,即array[1] = 3 ,第一个朋友的旁边是3
        int[] array = new int[n+1];
        //第一个小朋友就放到第i个位置上
        for(int i = 1;i<=n;i++){
          array[i] = scan.nextInt();
        }
        scan.close();
        //循环每一个学生,通过dfs找到他们环,记录和更新在max
        for(int i = 1;i<=n;i++){
          dfs(array,i);
        }
        System.out.println(max);
    }
    public static void dfs(int[] array,int i){
      //创建一个boolean数组,记录和array相同的位置有没有被访问,如果没有被访问,那么就通过该下标的指向继续遍历
      boolean[] count = new boolean[array.length];
      //进入循环的初始节点
      int res = i;
      //环的圈数
      int sum = 0;
      //初始化的count是用false填充的
      while(count[res]==false){
        //进来之后将当前位置改为true,代表这个节点已经进来过,防止死循环
        count[res] = true;
        //当前环的圈数+1
        sum++;
        //前往这个学生指向的下一个学生
        res = array[res];
      }
      //从环出来后,res就是环的初始节点,判断是否和我们传递进来的i相同,
      //如果相同,代表这个学生能够形成一个环,然后更新max即可
      if(res==i){
        max = Math.max(sum,max);
      }
    }
}

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值