Kosaraju算法---求解强连通分量
来源:互联网 发布:1920淘宝全屏轮播海报 编辑:程序博客网 时间:2024/05/16 14:54
有向图强连通分量在有向图G中,如果两个顶点Vi,Vj间(Vi>Vj)有一条从Vi到Vj的有向路径,同时还有一条从Vi到Vj的有向路径,则称这两个顶点强。连通(strongly connected),如果有向图G中的任意两个顶点都强连通,则称G是一个强连通图。
Kosaraju算法、Tarjan算法、Gabow算法皆为寻找有向图强连通分量的有效算法。但是在Tarjan 算法和 Gabow 算法的过程中,只需要进行一次的深度优先搜索,而Kosaraju算法需要两次DFS,因而相对 Kosaraju 算法较有效率。这些算法可简称为SSC(strongly connected components)算法;
Kosaraju 算法即为算法导论一书给出的算法,比较直观和易懂。这个算法可以说是最容易理解,最通用的算法,其比较关键的部分是同时应用了原图G和反图GT。 它利用了有向图的这样一个性质,一个图和他的transpose graph(边全部反向)具有相同的强连通分量!
## 算法步骤 ##
1) 创建一个空的栈 ‘S’ ,然后对图做DFS遍历. 在顶点访问完成后加入栈中。访问完成是说回溯返回时,而不是第一次发现该节点时。fillOrder()函数
2) 得到图转置,即将所有边反向。
3) 从S中依次弹出每个顶点,设为 ‘v’. 将v看做遍历的源点 (调用 DFSUtil(v)). 做第二次DFS遍历,可以找到以v为起点的强连通分量,打印出即可。
## 代码 ##
#include<iostream>#include<list>#include<stack>using namespace std;class Graph{ int V; //顶点个数 list<int> *adj; //邻接表 void fillOrder(int V, bool visited[], stack<int> &stack);//最晚完成的遍历顶点放在栈顶 void DFSUtil(int v, bool visited[]);//DFS打印以V为起点的边public: Graph(int V); void addEdge(int v, int w); void printSCCs();//打印所有的连通分量 Graph getTranspose();//得到当前图的转置图};Graph::Graph(int V){ this->V = V; adj = new list<int>[V];}void Graph::DFSUtil(int v, bool visited[]){ visited[v] = true; cout << v << " "; list<int>::iterator i; for (i = adj[v].begin(); i != adj[v].end();i++) { if (!visited[*i]) { DFSUtil(*i, visited); } }}Graph Graph::getTranspose(){ Graph g(V); for (int v = 0; v < V;v++) { list<int>::iterator i; for (i = adj[v].begin(); i != adj[v].end();++i) { g.adj[*i].push_back(v); } } return g;}void Graph::addEdge(int v, int w){ adj[v].push_back(w);}void Graph::fillOrder(int v, bool visited[], stack<int> &stack){ visited[v] = true; list<int>::iterator i; for (i = adj[v].begin(); i != adj[v].end();i++) { if (!visited[*i]) { fillOrder(*i, visited, stack); } } stack.push(v);}void Graph::printSCCs(){ stack<int> stack; bool *visited = new bool[V]; for (int i = 0; i < V;i++) { visited[i] = false; } for (int i = 0; i < V;i++) { if (visited[i]==false) { fillOrder(i, visited, stack);//根据完成时间压入栈中,而栈顶是完成时间最晚的顶点; } } //下面,我们来创建转置图 Graph gr = getTranspose(); //准备第二次DFS for (int i = 0; i < V;i++) { visited[i] = false; } while (stack.empty()==false) { int v = stack.top(); stack.pop(); //打印以v为起点的强连通分量 if (visited[v]==false) { gr.DFSUtil(v, visited); cout << endl; } }}//测试程序int main() { // 创建图 Graph g(5); g.addEdge(1, 0); g.addEdge(0, 2); g.addEdge(2, 1); g.addEdge(0, 3); g.addEdge(3, 4); cout << "Following are strongly connected components in given graph \n"; g.printSCCs(); return 0;}
0 0
- Kosaraju算法---求解强连通分量
- Kosaraju算法求解强连通分量
- 求解强连通分量算法之---Kosaraju算法
- 求解强连通分量算法之---Kosaraju算法
- Kosaraju算法解析: 求解图的强连通分量
- Kosaraju算法解析: 求解图的强连通分量
- 强连通分量 Kosaraju算法
- 强连通分量 -- Kosaraju算法
- 强连通分量-kosaraju算法
- 强连通分量 Kosaraju算法
- 强连通分量(Kosaraju算法)
- 强连通分量算法Kosaraju 和 Tarjan
- 强连通分量的Kosaraju算法
- 强连通分量 的 Kosaraju算法
- 强连通分量——kosaraju算法
- 强连通分量——Kosaraju算法
- POJ 2186 Kosaraju算法 强连通分量
- 强连通分量Kosaraju算法实现
- Android之获取手机上已安装的所有的应用程序的信息,并判断是否安装了某应用程序(系统程序或非系统应用程序判断)
- 单例设计模式的两种方法
- 20151226问题总结
- 学习笔记1: Activity 生命周期
- 设置progressbar的背景颜色
- Kosaraju算法---求解强连通分量
- Looper, Handler,Message关系解析
- BS架构ERP系统开发全系列之白金教程-主界面设计
- 努力让自己拥有一个初学者的心态,永远充满好奇、求知欲和赞叹
- 那一年,我们二十七八岁
- 数据库系统概论复习总结3 --- 第二章关系数据库标准语言SQL
- IIS——服务开启及本地发布网站图解(一)
- 抽象工厂模式
- [精]Oracle APEX 5.0 新手教程(一) Form表单