我知道这道题有多种解法,甚至暴力都可以满分,但是我在这里要介绍强连通分量的解法。
这题的题意太简单了,就是说每个人把自己的生日告诉别人,知道从别人的嘴里知道自己的生日。
很显然,一共进行的轮数就是最小的强连通分量的元素个数,因为如果形成了一个强连通分量,每个点都是可以相互到达的,所以结束肯定就是最早听到自己生日的那一次。
所以我们要求元素最小的那个强连通分量
代码:
#include<algorithm>
#include<cstdio>
using namespace std;
int son[200001],n,m,ans=999999999,group,low[200001],dfn[200001],st[200001],tot,now[200010],used[200001],popp[200001],a[200010],b[200010];
void add(int x,int y)
{
tot++;
now[tot]=son[x];
son[x]=tot;
}
int top,sum,cnt,totle;
void dfs(int deep)
{
st[++top]=deep;
dfn[deep]=++cnt;
low[deep]=dfn[deep];
int nnow=top;
for(int i=son[deep];i;i=now[i])
if(!used[b[i]])
{
if(!dfn[b[i]])
dfs(b[i]);
low[deep]=min(low[b[i]],low[deep]);
}
if(dfn[deep]==low[deep])
{
totle++;
if(top-nnow)ans=min(top-nnow+1,ans);
for(int i=nnow;i<=top;i++)
used[st[i]]=totle;
top=nnow-1;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]),add(i,b[i]);
for(int i=1;i<=n;i++)
if(!used[i])dfs(i);
printf("%d",ans);
}