【模板】有向图强连同分量

求强连通分量

要用到时间戳的概念

算了 直接给模板

ps:借鉴大白皮的写法

 1 # include<cstdio>
 2 # include<cstring>
 3 # include<stack>
 4 # include<algorithm>
 5 using namespace std;
 6 const int N=100000;
 7 const int M=500000;
 8 int n,m,dfs_clock,ecnt,scc_cnt;
 9 int fist[N],next[M],v[M],pre[N],low[N],scc_no[N];
10 stack<int>S;
11 void built(int a,int b){
12     v[++ecnt]=b;
13     next[ecnt]=fist[a];
14     fist[a]=ecnt;
15 }
16 void init(){
17     int a,b;
18     memset(fist,-1,sizeof(fist));
19     scanf("%d%d",&n,&m);
20     for(int i=1;i<=m;i++){
21         scanf("%d%d",&a,&b);
22         built(a,b);
23     }
24 }
25 int dfs(int u){
26     int lowu=pre[u]=++dfs_clock;
27     int lowv;
28     S.push(u);
29     for(int e=fist[u];e!=-1;e=next[e])
30     if(!pre[v[e]])
31     lowu=min(lowu,lowv=dfs(v[e]));
32     else if(!scc_no[v[e]])
33     lowu=min(lowu,pre[v[e]]);
34     low[u]=lowu;
35     if(pre[u]==low[u]){
36         scc_cnt++;
37         for(;;){
38             int x=S.top();S.pop();
39             scc_no[x]=scc_cnt;
40             if(x==u)break;
41         }
42     }
43     return low[u];
44 }
45 void find_scc(){
46     memset(pre,0,sizeof(pre));
47     memset(scc_no,0,sizeof(scc_no));
48     for(int i=1;i<=n;i++)
49     if(!pre[i])dfs(i);
50 }
51 void print(){
52     printf("%d",scc_cnt);
53 }
54 int main(){
55     init();
56     find_scc();
57     print();
58     return 0;
59 }
时间: 2024-11-03 21:51:15

【模板】有向图强连同分量的相关文章

有向图的强联通分量

最近学了有向图的强联通分量.有kosaraju算法,不过写着比tarjin麻烦.所以就只记录tarjin算法. 跟求无向图的双连通分量很相似,先贴代码. 1 void dfs(int u){ 2 dfn[u]=low[u]=++clk;//dfn序 3 stk[top++]=u;//压入栈内 4 for(int i=head[u];i;i=edge[i].nxt){ 5 int t=edge[i].to; 6 if(dfn[t]==0){//如果下一个节点是没有访问过的 7 dfs(t); 8

POJ 2186 Popular cows(Kosaraju+强联通分量模板)

题目链接:http://poj.org/problem?id=2186 题目大意:给定N头牛和M个有序对(A,B),(A,B)表示A牛认为B牛是红人,该关系具有传递性,如果牛A认为牛B是红人,牛B认为牛C是红人,那么牛A也认为牛C是红人.求被其他所有牛认为是红牛的牛的总数. 解题思路:把所有牛看成顶点,把有序对(A,B)看成从A到B的有向边,那么题目就变成了求所有顶点都可到达的顶点的总数.我们可以得到一个结论,如果一个强连通分量里有一头牛被认为是红人,那么该强联通分量里的所有牛都是红人,这显然是

『Tarjan算法 有向图的强连通分量』

有向图的强连通分量 定义:在有向图\(G\)中,如果两个顶点\(v_i,v_j\)间\((v_i>v_j)\)有一条从\(v_i\)到\(v_j\)的有向路径,同时还有一条从\(v_j\)到\(v_i\)的有向路径,则称两个顶点强连通(strongly connected).如果有向图\(G\)的每两个顶点都强连通,称\(G\)是一个强连通图.有向图的极大强连通子图,称为强连通分量(strongly connected components). 万能的Tarjan算法也可以帮助我们求解有向图的强

【小结】强联通分量分解

强联通分量 在一个有向图的顶点子集S中,对?(u,v),如果都能找到一条从u到v的路径,那么就称S是强联通的.如果向S中加入任何一个其他顶点后S都不再是强联通的,就称S时原图的一个强联通分量. 显然,如果把所有的强联通分量都缩点,原图将变成一个DAG SCC的求解可通过两次dfs实现,第一次在原图中后续遍历,标号:第二遍将所有边反向后,从编号最大的点开始遍历,每次都可得到一个SCC. #include <cstdio> #include <cstring> #include <

[CF #236 (Div. 2) E] Strictly Positive Matrix(强联通分量)

题目:http://codeforces.com/contest/402/problem/E 题意:给你一个矩阵a,判断是否存在k,使得a^k这个矩阵全部元素都大于0 分析:把矩阵当作01矩阵,超过1的都当作1,那么a矩阵可表示一个有向图的走一次的连通性,则a^k表示有向图走K次的连通性.既然要求最后都没0,即走了K次后,每个点都能互通,这也说明这个图必然是只有一个强联通分量.于是判断k的存在有无,也就是判断a矩阵表示的有向图是不是只有一个强联通分量.

51nod 1076 2条不相交的路径 无向图强联通分量 trajan算法

1076 2条不相交的路径 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 给出一个无向图G的顶点V和边E.进行Q次查询,查询从G的某个顶点V[s]到另一个顶点V[t],是否存在2条不相交的路径.(两条路径不经过相同的边) (注,无向图中不存在重边,也就是说确定起点和终点,他们之间最多只有1条路) Input 第1行:2个数M N,中间用空格分开,M是顶点的数量,N是边的数量.(2 <= M <= 25000, 1 <= N <=

【POJ1236】Network of Schools 强联通分量缩点(本文kosaraju)

/*不要说这题多水之类的--我只是想记一下kosaraju这种屌炸天的dfs序延伸算法(说不定能加到我的ygylca里面)*/ 题意神马的都不说了,好吧,就是给你个图,n个点,然后n行每行都描述该点的出边,图建完了,然后缩点,然后问多少个点没有入度,再问需要加几条边可以让图变强联通图. 强联通图:图中任意两点之间都能互相到达(前提得是有向图你懂的,无向图就有点乱了,根本不要算法了,暴搜就好了) 强联通分量:同强联通图,不过是图中一部分. 缩点,把一个分量视为一个点,缩起来(一般不缩,都是记录每个

强联通分量之kosaraju算法

首先定义:强联通分量是有向图G=(V, E)的最大结点集合,满足该集合中的任意一对结点v和u,路径vu和uv同时存在. kosaraju算法用来寻找强联通分量.对于图G,它首先随便找个结点dfs,求出每个节点最后一次访问的时间戳f(x),然后我们建立反图Gt,接着根据倒序的时间戳来dfs每个节点,每次dfs到的结点集合就是一个强联通分量.事实上这个算法的思想和拓扑排序类似. 我们来证明它(注意这里面的图指原图,而不是反图): 引理:对于G中的两个强联通分量C和C',若点u属于C,点v属于C',且

Tarjan的强联通分量

求强联通分量有很多种. <C++信息学奥赛一本通>  中讲过一个dfs求强联通分量的算法Kosdaraju,为了骗字数我就待会简单的说说.然而我们这篇文章的主体是Tarjan,所以我肯定说完之后再赞扬一下Tarjan大法好是不是 首先我们讲一下强联通分量 强联通分量指的是图的一个子图.在这个子图中,任意两个节点都可以互相到达.从定义上我们就可以看出是一个有向图来,因为任意一个无向图都符合该定义. 而它的标准定义是:有向图中任意两点都联通的最大子图. 咳咳,首先庆祝一下哈--本人博客的第一张图.