强连通分量tarjan模板复习

Posted lazytear

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了强连通分量tarjan模板复习相关的知识,希望对你有一定的参考价值。

对于一个有向图定点的子集,在该子集中任取两点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模板复习的主要内容,如果未能解决你的问题,请参考以下文章

tarjan强连通分量缩点模板

tarjan算法(强连通分量 + 强连通分量缩点 + 桥 + 割点 + LCA)

强连通分量——tarjan算法

HDU 1269 迷宫城堡 tarjan算法求强连通分量

Tarjan求强连通分量求桥和割点模板

tarjan求强连通分量(模板)