强连通分量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 }
时间: 2024-11-05 19:15:24

强连通分量tarjan模板复习的相关文章

图之强连通、强连通图、强连通分量 Tarjan算法

强连通分量 简介 在阅读下列内容之前,请务必了解图论基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Components,SCC)的定义是:极大的强连通子图. 这里想要介绍的是如何来求强连通分量. Tarjan 算法 Robert E. Tarjan (1948~) 美国人. Tarjan 发明了很多算法结构.光 Tarjan 算法就有很多,比如求各种联通分量的 Tarjan 算法,求 LCA(Lowest Comm

强连通分量(tarjan求强连通分量)

双DFS方法就是正dfs扫一遍,然后将边反向dfs扫一遍.<挑战程序设计>上有说明. 双dfs代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 6 using namespace std; 7 const int MAXN = 1e4 + 5; 8 vector <int> G[MAXN]; //图的邻接表

ZOJ 3795 Grouping 强连通分量-tarjan

一开始我还天真的一遍DFS求出最长链以为就可以了 不过发现存在有向环,即强连通分量SCC,有向环里的每个点都是可比的,都要分别给个集合才行,最后应该把这些强连通分量缩成一个点,最后保证图里是 有向无环图才行,这个时候再找最长链,当然缩点之后的scc是有权值的,不能只看成1,缩点完了之后,用记忆化搜索DP就可以再On的复杂度内求出结果 所以现学了一下SCC-Tarjan,所谓Scc-tarjan,就是找到强连通分量并且缩点,特别好用,其原理就是利用dfs时间戳,每个点有自己的时间戳,同时再开一个记

HDU 1269 强连通分量tarjan算法

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6655    Accepted Submission(s): 2973 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房

强连通分量tarjan

#include<iostream>//强连通分量tarjan #include<cstdio> #include<algorithm> #include<queue> #include<cstring> using namespace std; #define maxn 400010 #define INF 1e18 int low[maxn],dfn[maxn],sta[maxn],d[maxn]/*value*/,dis[maxn]/*to

tarjan求强连通分量(模板)

https://www.luogu.org/problem/P2341 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=50010; int pre[maxn],other[maxn],last[maxn],l; int n,m; int dfn[maxn],low[maxn],ans[maxn],st[maxn],belong[maxn

求图的强连通分量--tarjan算法

一:tarjan算法详解 ?思想: ? ?做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间.(也就是之后的深搜所能到达的最小开始时间)初始时dfn[i]=low[i] ? ?在DFS过程中会形成一搜索树.在搜索树上越先遍历到的节点,显然dfn的值就越小. ? ?DFS过程中,碰到哪个节点,就将哪个节点入栈.栈中节点只有在其所属的强连通分量已经全部求出时,才会出栈. ?

强连通分量--tarjan

tarjan 算法思想 dfs,如果还能返回到起点,说明这些点是强联通的 模板 int n,m,idx,top,cnt; int dfn[maxn]; //这个点是第几个被访问的 int low[maxn]; //这个点所能到的点的dfn的最小值 bool vis[maxn]; //是否在s中 int s[maxn]; //栈 vector<int> a[maxn]; //图 void tarjan(int u) { dfn[u] = low[u] = ++idx; s[++top] = u;

【强连通分量&#183;Tarjan】bzoj1179: [Apio2009]Atm

新博的第一发! 因为这几天切了几道强连通分量,所以从这里begin [题目描述] Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定,在每个路口都设立了一个Siruseri 银行的ATM 取款机.令人奇怪的是,Siruseri的酒吧也都设在路口,虽然并不是每个路口都设有酒吧.Banditji 计划实施Siruseri 有史以来最惊天动地的ATM 抢劫.他将从市中心出发,沿着单向道路行驶,抢劫所有他途径的ATM 机,最终他将在一个酒吧庆祝他的胜利.使用高超的黑客技术,他获