[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 }