码迷,mamicode.com
首页 > 其他好文 > 详细

强连通分量tarjan模板复习

时间:2017-05-22 17:50:41      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:ret   com   基于   logs   ges   log   printf   main   str   

对于一个有向图定点的子集,在该子集中任取两点u与v,都能找到一条从u到v的路径,则称该子集是强连通的。若该集合加入到任意点集中,它都不再强连通,则称这个子集是原图的一个强连通分量。任意一张图都可以分解成若干个不相交的强连通分量。这是强连通分量分解。把分解后的强连通分量缩成一个顶点,就可以得到一个有向无环图。

如图:技术分享

 

求一张图的强连通分量的个数,常用tarjan算法,它是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。

模板如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 int n,m;
 8 struct node{
 9     int fr,to;
10 }ed[50001];
11 bool vis[10001];
12 int dfs[10001],stack[10001],head[10001],low[10005];
13 int tot=0,ans=0,in=0,num=0;
14 void add(int u,int v){
15     ed[++num].fr=head[u];head[u]=num;ed[num].to=v;
16 }
17 void tarjan(int x){
18     dfs[x]=low[x]=++tot;
19     stack[++in]=x;
20     vis[stack[in]]=1;
21     int i;
22     for(i=head[x];i;i=ed[i].fr){
23         if(!dfs[ed[i].to]){
24             tarjan(ed[i].to);
25         }
26         if(vis[ed[i].to]){
27             low[x]=min(low[x],low[ed[i].to]);
28         }
29     }
30     if(low[x]==dfs[x]){
31         for(++ans;stack[in+1]!=x;)  vis[stack[in--]]=0;
32     }
33 }
34 int main(){
35     scanf("%d%d",&n,&m);
36     int i;
37     for(i=1;i<=m;i++){
38         int x,y;
39         scanf("%d%d",&x,&y);
40         add(x,y);
41     }
42     for(i=1;i<=n;i++)  if(!dfs[i])  tarjan(i);
43     printf("%d\n",ans);
44     return 0;
45 }

 

强连通分量tarjan模板复习

标签:ret   com   基于   logs   ges   log   printf   main   str   

原文地址:http://www.cnblogs.com/lazytear/p/6890341.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!