题目链接:https://www.luogu.org/problem/P2661
题意:每个人都有一个传递对象,一开始每个人都只知道自己的生日,每一轮都会把自己所知道生日告诉给传递对象,当从别人处听得自己生日时游戏结束,求问最少可以玩几轮游戏。
分析:就是找最小环,dfs来做,两个vis数组做标记(代码里把一个记为used),used数组属于常规的vis数组,标示这个点已经访问过了,不用走了,vis数组是用来求最小环的,在没次查找中设置。具体看代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+7; const int N=maxn*20; const ll inf=0x3f3f3f3f; #define mem0(a) memset(a,0,sizeof(a)) int d[maxn]; int ans=inf; int step[maxn];//用来记录在一个循环里第一次经过一个点时经过的边数 int vis[maxn],used[maxn];//vis数组记录本次查找中已经经过的点(用来判断是否是环),used数组用来标记该点已经走过一次了,不用再走了 void dfs(int nd,int num){//nd,num分别是当前到的结点和走到的步数 if(used[nd]) return; if(vis[nd]){ ans=min(ans,num-step[nd]); } else{ vis[nd]=1; step[nd]=num; dfs(d[nd],num+1); used[nd]=1; } } int main(){ int n;scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&d[i]); } for(int i=1;i<=n;i++){ dfs(i,0); } cout<<ans<<endl; return 0; }