题解 P2661 【信息传递】

由题意得,只有强连通分量之间传递才能最终得到自己的编号。

可以用\(tarjan\)找出强连通分量,并从中找出大于1的最小的强连通分量则是最小的游戏回合数

//AC代码
//找SCC 
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<stack>
#define N 200010
using namespace std;
int n;
int Root[N],Next[N],v[N],cnt;
int scc[N],scccnt,dfn[N],low[N],dfscnt;
int ans[N];
stack<int>st;
inline void add(int _u,int _v)
{
	v[++cnt]=_v;
	Next[cnt]=Root[_u];
	Root[_u]=cnt;
}
inline void tarjan(int u){
    dfn[u]=low[u]=++dfscnt;
    st.push(u);
    for(int x=Root[u];x!=0;x=Next[x]){
        if(!dfn[v[x]]){
			tarjan(v[x]); 
			low[u]=min(low[u],low[v[x]]);
		}
        else if(!scc[v[x]]) low[u]=min(low[u],dfn[v[x]]);
    }
    int t;
    if(low[u]==dfn[u]){
        scccnt++;
        do{
            t=st.top(); st.pop();
            scc[t]=scccnt,ans[scccnt]+=1;
        }while(t!=u);
    }
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		int V;scanf("%d",&V);
		add(i,V);
	}
	for(int i=1;i<=n;++i)
		if(!dfn[i])tarjan(i);
	int Min=0x3f3f3f3f;
	for(int i=1;i<=n;++i){
		if(ans[i]>1)Min=min(Min,ans[i]);
	}
	printf("%d",Min);
	return 0;
}
上一篇:树链剖分の学习笔记


下一篇:NC50403 嗅探器