找最小环 洛谷P2661

题目链接: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;
}

 

posted @ 2019-09-10 21:12  清酒令  阅读(149)  评论(0编辑  收藏  举报