图的强连通分量-Kosaraju算法

输入一个有向图,计算每个节点所在强连通分量的编号,输出强连通分量的个数

 1 #include<iostream>
 2 #include<cstring>
 3 #include<vector>
 4 using namespace std;
 5 const int maxn=1024;
 6 struct Edge{
 7     int go,next;
 8 };
 9 int vis[maxn],count=0,book[maxn];
10 vector<Edge> G,G2;
11 vector<int> S;
12 int end[maxn],end2[maxn];
13 void add(int from,int to){Edge e;e.go=to;e.next=end[from];G.push_back(e);end[from]=G.size()-1;}
14 void add2(int from,int to){Edge e;e.go=to;e.next=end2[from];G2.push_back(e);end2[from]=G2.size()-1;}
15 void dfs(int u)
16 {
17     vis[u]=1;
18     for(int i=end[u];i;i=G[i].next){
19         int go=G[i].go;
20         if(!vis[go]) dfs(go);
21     }
22     S.push_back(u);
23 }
24 void dfs2(int u)
25 {
26     book[u]=count;
27     for(int i=end2[u];i;i=G2[i].next){
28         int go=G2[i].go;
29         if(!book[go]) dfs2(go);
30     }
31 }
32 void init()
33 {
34     memset(vis,0,sizeof(vis));
35     memset(end,0,sizeof(end));
36     memset(end2,0,sizeof(end2));
37     memset(book,0,sizeof(book));
38 }
39 int main()
40 {
41     int n,m,a,b;
42     scanf("%d %d",&n,&m);
43     init();
44     for(int i=1;i<=m;i++)
45     {
46         scanf("%d %d",&a,&b);
47         add(a,b);
48         add2(b,a);
49     }
50     for(int i=1;i<=n;i++) if(!vis[i]) dfs(i);
51     for(int i=n-1;i>=0;i--) if(!book[S[i]]){
52         count++;
53         dfs2(S[i]);
54     }
55     cout<<count;
56     return 0;
57 }
时间: 2024-12-10 23:04:29

图的强连通分量-Kosaraju算法的相关文章

【Algorithms IV】求解强连通分量 Kosaraju算法

[Algorithms IV]求解强连通分量 Kosaraju算法 Kosaraju算法(也被称为Kosaraju–Sharir算法)是一个在线性时间内寻找一个有向图中的强连通分量的算法. 这个拗口的名字来自他的作者,但是查不到他的生平.应该是个印度人. 求解问题:要求有向图中的强连通分量的个数/划分 算法步骤: 即: 对输入G, 反转边获得逆向图GR     用DFS算法对图遍历得到reversePost序列(遍历图后push 到一个stack里,之后stack逆序弹出) 依次对reverse

CSU 1612: Destroy Tunnels 强连通分量 Kosaraju算法

链接 :  http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1612 题意: 给一个矩阵A 大小N*N, B = A^1 + A^2 + A^3 + .... A^n , B中是否存在非0项. 题目可以转化为 N个点 编号为1-n, 对于任意点v,经过一些任意的步长到达u (u为所有点集的任意一个).离散数学里有图的矩阵相关知识 A^k代表了矩阵中从i到j的步长为k的方法数. 题目就是求整个图是否强连通. 学习了 Kosaraju算法 可以轻

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

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

图论算法之(强连通分量&lt;Kosaraju&gt;)

强连通分量算法有3个之多,现在介绍这种名字叫做kosaraju算法. 这个算法基于两个事实,1.原图G与逆置图GT拥有相同的强连通分量,这肯定是正确的 2.任意一个子节点存放皆后于父节点,也就是说所有只有当所有子节点都入栈了,父节点才入栈 这种在递归调用之后将顶点入队列的方式叫逆后续排序(reverse post),在无环图中这种排序方式就是拓扑排序. 简要证明: 1. 第一次DFS有向图G时,最后记录下的节点必为最后一棵生成树的根节点. 证明:假设最后记录下节点不是树根,则必存在一节点为树根,

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

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

POJ2186 Popular Cows 【强连通分量Kosaraju】

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23445   Accepted: 9605 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M &l

求有向图的强连通分量的算法

下面是求有向图的强连通分量的算法的代码: import java.util.Scanner; class Qiufenliang//定义求强连通分量的类 { String lu="";//定义的一个字符型变量,记录强连通分量的路径 public static int s=0; public void qiu(int a[][],int l)//定义函数,参数a为二维数组,参数l为数组的维数 { int t=0;//定义int型变量,进行数量的统计 for(int i=1;i<l;

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房

Kosaraju算法解析: 求解图的强连通分量

1. 定义 连通分量:在无向图中,即为连通子图. 上图中,总共有四个连通分量.顶点A.B.C.D构成了一个连通分量,顶点E构成了一个连通分量,顶点F,G和H,I分别构成了两个连通分量. 强连通分量:有向图中,尽可能多的若干顶点组成的子图中,这些顶点都是相互可到达的,则这些顶点成为一个强连通分量. 上图中有三个强连通分量,分别是a.b.e以及f.g和c.d.h. 2. 连通分量的求解方法 对于一个无向图的连通分量,从连通分量的任意一个顶点开始,进行一次DFS,一定能遍历这个连通分量的所有顶点.所以