[Noip2015] 信息传递

我知道这道题有多种解法,甚至暴力都可以满分,但是我在这里要介绍强连通分量的解法。

这题的题意太简单了,就是说每个人把自己的生日告诉别人,知道从别人的嘴里知道自己的生日。

很显然,一共进行的轮数就是最小的强连通分量的元素个数,因为如果形成了一个强连通分量,每个点都是可以相互到达的,所以结束肯定就是最早听到自己生日的那一次。

所以我们要求元素最小的那个强连通分量

代码:

 1 #include<algorithm>
 2 #include<cstdio>
 3 using namespace std;
 4 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];
 5 void add(int x,int y)
 6 {
 7     tot++;
 8     now[tot]=son[x];
 9     son[x]=tot;
10 }
11 int top,sum,cnt,totle;
12 void dfs(int deep)
13 {
14     st[++top]=deep;
15     dfn[deep]=++cnt;
16     low[deep]=dfn[deep];
17     int nnow=top;
18     for(int i=son[deep];i;i=now[i])
19         if(!used[b[i]])
20         {
21             if(!dfn[b[i]])
22                 dfs(b[i]);
23             low[deep]=min(low[b[i]],low[deep]);
24         }
25     if(dfn[deep]==low[deep])
26     {
27         totle++;
28         if(top-nnow)ans=min(top-nnow+1,ans);
29         for(int i=nnow;i<=top;i++)
30             used[st[i]]=totle;
31         top=nnow-1;
32     }
33 }
34 int main()
35 {
36     scanf("%d",&n);
37     for(int i=1;i<=n;i++)
38         scanf("%d",&b[i]),add(i,b[i]);
39     for(int i=1;i<=n;i++)
40         if(!used[i])dfs(i);
41     printf("%d",ans);
42 }
原文地址:https://www.cnblogs.com/lcxer/p/9441703.html