强连通分量Kosaraju算法
2011-08-04 20:21
381 查看
• 基本思路:
• 这个算法是最通用的算法,其比较关键的部分是同时应用了原图G和反图GT。(步骤1)先用对原图G进行深搜记录时间结f(n)。(步骤2)选择f(n)最大的点在深搜得到各个强连通分量。
•
•
•2. 伪代码
• Kosaraju_Algorithm:
• step1:对原图G进行深度优先遍历,记录每个节点的离开时间。
• step2:选择具有最晚离开时间的顶点,对反图GT进行遍历,删除能够遍历到的顶点,这些顶点构成一个强连通分量。
• step3:如果还有顶点没有删除,继续step2,否则算法结束。
如下图所视:
• 这个算法是最通用的算法,其比较关键的部分是同时应用了原图G和反图GT。(步骤1)先用对原图G进行深搜记录时间结f(n)。(步骤2)选择f(n)最大的点在深搜得到各个强连通分量。
•
•
•2. 伪代码
• Kosaraju_Algorithm:
• step1:对原图G进行深度优先遍历,记录每个节点的离开时间。
• step2:选择具有最晚离开时间的顶点,对反图GT进行遍历,删除能够遍历到的顶点,这些顶点构成一个强连通分量。
• step3:如果还有顶点没有删除,继续step2,否则算法结束。
如下图所视:
poj2186
#include <iostream> #include <cstring> #include <vector> using namespace std; const int MAX = 105;/****** * v为原图 * rv为所有边逆向后的新图 * s记录第一遍dfs后各点的结束时间:最晚结束的在栈顶 ******/ vector<int> v[MAX], rv[MAX], s;/****** * num[v]点v所属连通分量的编号 * tree_n[i]第i个连通分量内点的个数 ******/ int num[MAX], tree_n[MAX], cnt; bool mark[MAX],ml[MAX]; void dfs_1(int x)//第一步计算dfs结束时间,将时间由小到大对应的数入s { mark[x] = 1; for (int i = 0; i < v[x].size(); ++i) { if (!mark[v[x][i]]) { dfs_1(v[x][i]); } } s.push_back(x); } void dfs_2(int x)//从s的尾取数再rv中dfs { num[x] = cnt; //点v所属连通分量的编号为cnt ++tree_n[cnt]; //记录编号为cnt的连通分量中的元数个数 mark[x] = 1; for (int i = 0; i < rv[x].size(); ++i) { if (!mark[rv[x][i]]) { dfs_2(rv[x][i]); } } } void cal(int n) { int i,j; memset(mark, 0, sizeof(mark)); memset(ml,0,sizeof(ml)); for (i = 1; i <= n; ++i) { for (j = 0; j < v[i].size(); ++j) { int x = v[i][j]; if (num[i] != num[x])//检查强连通分量是否有出度,有就对应的mark[i]=1 { mark[num[x]] = 1; ml[num[i]]=1; } } } int flag = 0,flg =0, ans; for (i = 1; i <= cnt; ++i) //检查有几个强连通分量的入度为0 { if (!mark[i]) { ans = i; ++flag; } if (!ml[i]) { ++flg; } } cout<<flag<<endl; if(cnt!=1) { flg=flag>flg? flag:flg; cout<<flg<<endl; } else cout<<0<<endl; } int main() { int a, b, n, i, j; scanf("%d",&n); for(i=1;i<=n;i++) { while(cin>>a&&a) { v[i].push_back(a); rv[a].push_back(i); } } for (i = 1; i <= n; ++i) { if (!mark[i]) { dfs_1(i); } } memset(mark, 0, sizeof(mark)); memset(tree_n, 0, sizeof(tree_n)); cnt = 0; //cnt记录连通分量的个数 for (i = s.size() - 1; i >= 0; --i) { if (!mark[s[i]]) { ++cnt; dfs_2(s[i]); } } cal(n); return 0; }
poj1236
#include <iostream> #include <cstring> #include <vector> using namespace std; const int MAX = 10005;/****** * v为原图 * rv为所有边逆向后的新图 * s记录第一遍dfs后各点的结束时间:最晚结束的在栈顶 ******/ vector<int> v[MAX], rv[MAX], s;/****** * num[v]点v所属连通分量的编号 * tree_n[i]第i个连通分量内点的个数 ******/ int num[MAX], tree_n[MAX], cnt;bool mark[MAX]; void dfs_1(int x)//第一步计算dfs结束时间,将时间由小到大对应的数入s { mark[x] = 1; for (int i = 0; i < v[x].size(); ++i) { if (!mark[v[x][i]]) { dfs_1(v[x][i]); } } s.push_back(x); } void dfs_2(int x)//从s的尾取数再rv中dfs { num[x] = cnt; //点v所属连通分量的编号为cnt ++tree_n[cnt]; //记录编号为cnt的连通分量中的元数个数 mark[x] = 1; for (int i = 0; i < rv[x].size(); ++i) { if (!mark[rv[x][i]]) { dfs_2(rv[x][i]); } } } void cal(int n) { int i,j; memset(mark, 0, sizeof(mark)); for (i = 1; i <= n; ++i) { for (j = 0; j < v[i].size(); ++j) { int x = v[i][j]; if (num[i] != num[x])//检查强连通分量是否有出度,有就对应的mark[i]=1 { mark[num[i]] = 1; } } } int flag = 0, ans; for (i = 1; i <= cnt; ++i) //检查有几个强连通分量的入度为0 { if (!mark[i]) { ans = i; ++flag; } } if (flag == 1) //如果只有一个强连通分量的入度为0,则输出应的tree_n[i]为要的答案,否则没有 { printf("%d\n", tree_n[ans]); } else { printf("0\n"); } } int main() { int a, b, n, m, i, j; scanf("%d%d", &n, &m); for (i = 0; i < m; ++i) { scanf("%d%d", &a, &b); v[a].push_back(b); rv[b].push_back(a); } for (i = 1; i <= n; ++i) { if (!mark[i]) { dfs_1(i); } } memset(mark, 0, sizeof(mark)); memset(tree_n, 0, sizeof(tree_n)); cnt = 0; //cnt记录连通分量的个数 for (i = s.size() - 1; i >= 0; --i) { if (!mark[s[i]]) { ++cnt; dfs_2(s[i]); } } cal(n); return 0; }
相关文章推荐
- 半连通分量--Tarjan/Kosaraju算法
- Kosaraju算法求最强连通分量
- Kosaraju算法求有向强连通分量,缩点后是DAG的拓扑序列(从小到大)
- 有向图----强连通分量问题(Kosaraju算法)
- 强连通分量 Kosaraju算法
- 强连通分量(Kosaraju算法)
- [图论] 有向图强连通分量 (kosaraju算法,Tarjan算法)
- 强连通分量 Kosaraju算法
- 求有向图的强连通分量个数 之 Kosaraju算法
- poj2186Popular Cows(Kosaraju算法--有向图的强连通分量的分解)
- 强连通分量分解 Kosaraju算法 (poj 2186 Popular Cows)
- 强连通分量——Kosaraju算法
- 强连通分量——[Kosaraju算法]
- Kosaraju算法解析: 求解图的强连通分量
- 有向图的强连通分量之Kosaraju算法
- 一句话之--tarjan算法、kosaraju算法,求强连通分量
- 强连通分量_Kosaraju算法
- 强连通分量 -- Kosaraju算法
- 有向图强连通分量的Tarjan算法和Kosaraju算法
- 强连通分量——kosaraju算法