本文给出了C++程序和Python程序。

tarjan算法是由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法。

程序来源:Tarjan’s Algorithm to find Strongly Connected Components。

百度百科: tarjan算法。

维基百科:Tarjan's strongly connected components algorithm。 

参考文章:Tarjan算法。

C++程序:

// A C++ program to find strongly connected components in a given
// directed graph using Tarjan's algorithm (single DFS)
#include<iostream>
#include <list>
#include <stack>
#define NIL -1
using namespace std;// A class that represents an directed graph
class Graph
{int V;    // No. of verticeslist<int> *adj;    // A dynamic array of adjacency lists// A Recursive DFS based function used by SCC()void SCCUtil(int u, int disc[], int low[],stack<int> *st, bool stackMember[]);
public:Graph(int V);   // Constructorvoid addEdge(int v, int w);   // function to add an edge to graphvoid SCC();    // prints strongly connected components
};Graph::Graph(int V)
{this->V = V;adj = new list<int>[V];
}void Graph::addEdge(int v, int w)
{adj[v].push_back(w);
}// A recursive function that finds and prints strongly connected
// components using DFS traversal
// u --> The vertex to be visited next
// disc[] --> Stores discovery times of visited vertices
// low[] -- >> earliest visited vertex (the vertex with minimum
//             discovery time) that can be reached from subtree
//             rooted with current vertex
// *st -- >> To store all the connected ancestors (could be part
//           of SCC)
// stackMember[] --> bit/index array for faster check whether
//                  a node is in stack
void Graph::SCCUtil(int u, int disc[], int low[], stack<int> *st,bool stackMember[])
{// A static variable is used for simplicity, we can avoid use// of static variable by passing a pointer.static int time = 0;// Initialize discovery time and low valuedisc[u] = low[u] = ++time;st->push(u);stackMember[u] = true;// Go through all vertices adjacent to thislist<int>::iterator i;for (i = adj[u].begin(); i != adj[u].end(); ++i){int v = *i;  // v is current adjacent of 'u'// If v is not visited yet, then recur for itif (disc[v] == -1){SCCUtil(v, disc, low, st, stackMember);// Check if the subtree rooted with 'v' has a// connection to one of the ancestors of 'u'// Case 1 (per above discussion on Disc and Low value)low[u]  = min(low[u], low[v]);}// Update low value of 'u' only of 'v' is still in stack// (i.e. it's a back edge, not cross edge).// Case 2 (per above discussion on Disc and Low value)else if (stackMember[v] == true)low[u]  = min(low[u], disc[v]);}// head node found, pop the stack and print an SCCint w = 0;  // To store stack extracted verticesif (low[u] == disc[u]){while (st->top() != u){w = (int) st->top();cout << w << " ";stackMember[w] = false;st->pop();}w = (int) st->top();cout << w << "\n";stackMember[w] = false;st->pop();}
}// The function to do DFS traversal. It uses SCCUtil()
void Graph::SCC()
{int *disc = new int[V];int *low = new int[V];bool *stackMember = new bool[V];stack<int> *st = new stack<int>();// Initialize disc and low, and stackMember arraysfor (int i = 0; i < V; i++){disc[i] = NIL;low[i] = NIL;stackMember[i] = false;}// Call the recursive helper function to find strongly// connected components in DFS tree with vertex 'i'for (int i = 0; i < V; i++)if (disc[i] == NIL)SCCUtil(i, disc, low, st, stackMember);
}// Driver program to test above function
int main()
{cout << "\nSCCs in first graph \n";Graph g1(5);g1.addEdge(1, 0);g1.addEdge(0, 2);g1.addEdge(2, 1);g1.addEdge(0, 3);g1.addEdge(3, 4);g1.SCC();cout << "\nSCCs in second graph \n";Graph g2(4);g2.addEdge(0, 1);g2.addEdge(1, 2);g2.addEdge(2, 3);g2.SCC();cout << "\nSCCs in third graph \n";Graph g3(7);g3.addEdge(0, 1);g3.addEdge(1, 2);g3.addEdge(2, 0);g3.addEdge(1, 3);g3.addEdge(1, 4);g3.addEdge(1, 6);g3.addEdge(3, 5);g3.addEdge(4, 5);g3.SCC();cout << "\nSCCs in fourth graph \n";Graph g4(11);g4.addEdge(0,1);g4.addEdge(0,3);g4.addEdge(1,2);g4.addEdge(1,4);g4.addEdge(2,0);g4.addEdge(2,6);g4.addEdge(3,2);g4.addEdge(4,5);g4.addEdge(4,6);g4.addEdge(5,6);g4.addEdge(5,7);g4.addEdge(5,8);g4.addEdge(5,9);g4.addEdge(6,4);g4.addEdge(7,9);g4.addEdge(8,9);g4.addEdge(9,8);g4.SCC();cout << "\nSCCs in fifth graph \n";Graph g5(5);g5.addEdge(0,1);g5.addEdge(1,2);g5.addEdge(2,3);g5.addEdge(2,4);g5.addEdge(3,0);g5.addEdge(4,2);g5.SCC();return 0;
}

程序运行输出:

SCCs in first graph
4
3
1 2 0SCCs in second graph
3
2
1
0SCCs in third graph
5
3
4
6
2 1 0SCCs in fourth graph
8 9
7
5 4 6
3 2 1 0
10SCCs in fifth graph
4 3 2 1 0 

Python程序:

# Python program to find strongly connected components in a given
# directed graph using Tarjan's algorithm (single DFS)
#Complexity : O(V+E)from collections import defaultdict#This class represents an directed graph
# using adjacency list representation
class Graph:def __init__(self,vertices):#No. of verticesself.V= vertices # default dictionary to store graphself.graph = defaultdict(list) self.Time = 0# function to add an edge to graphdef addEdge(self,u,v):self.graph[u].append(v)'''A recursive function that find finds and prints strongly connectedcomponents using DFS traversalu --> The vertex to be visited nextdisc[] --> Stores discovery times of visited verticeslow[] -- >> earliest visited vertex (the vertex with minimumdiscovery time) that can be reached from subtreerooted with current vertexst -- >> To store all the connected ancestors (could be partof SCC)stackMember[] --> bit/index array for faster check whethera node is in stack'''def SCCUtil(self,u, low, disc, stackMember, st):# Initialize discovery time and low valuedisc[u] = self.Timelow[u] = self.Timeself.Time += 1stackMember[u] = Truest.append(u)# Go through all vertices adjacent to thisfor v in self.graph[u]:# If v is not visited yet, then recur for itif disc[v] == -1 :self.SCCUtil(v, low, disc, stackMember, st)# Check if the subtree rooted with v has a connection to# one of the ancestors of u# Case 1 (per above discussion on Disc and Low value)low[u] = min(low[u], low[v])elif stackMember[v] == True: '''Update low value of 'u' only if 'v' is still in stack(i.e. it's a back edge, not cross edge).Case 2 (per above discussion on Disc and Low value) '''low[u] = min(low[u], disc[v])# head node found, pop the stack and print an SCCw = -1 #To store stack extracted verticesif low[u] == disc[u]:while w != u:w = st.pop()print w,stackMember[w] = Falseprint""#The function to do DFS traversal. # It uses recursive SCCUtil()def SCC(self):# Mark all the vertices as not visited # and Initialize parent and visited, # and ap(articulation point) arraysdisc = [-1] * (self.V)low = [-1] * (self.V)stackMember = [False] * (self.V)st =[]# Call the recursive helper function # to find articulation points# in DFS tree rooted with vertex 'i'for i in range(self.V):if disc[i] == -1:self.SCCUtil(i, low, disc, stackMember, st)# Create a graph given in the above diagram
g1 = Graph(5)
g1.addEdge(1, 0)
g1.addEdge(0, 2)
g1.addEdge(2, 1)
g1.addEdge(0, 3)
g1.addEdge(3, 4)
print "SSC in first graph "
g1.SCC()g2 = Graph(4)
g2.addEdge(0, 1)
g2.addEdge(1, 2)
g2.addEdge(2, 3)
print "\nSSC in second graph "
g2.SCC()g3 = Graph(7)
g3.addEdge(0, 1)
g3.addEdge(1, 2)
g3.addEdge(2, 0)
g3.addEdge(1, 3)
g3.addEdge(1, 4)
g3.addEdge(1, 6)
g3.addEdge(3, 5)
g3.addEdge(4, 5)
print "\nSSC in third graph "
g3.SCC()g4 = Graph(11)
g4.addEdge(0, 1)
g4.addEdge(0, 3)
g4.addEdge(1, 2)
g4.addEdge(1, 4)
g4.addEdge(2, 0)
g4.addEdge(2, 6)
g4.addEdge(3, 2)
g4.addEdge(4, 5)
g4.addEdge(4, 6)
g4.addEdge(5, 6)
g4.addEdge(5, 7)
g4.addEdge(5, 8)
g4.addEdge(5, 9)
g4.addEdge(6, 4)
g4.addEdge(7, 9)
g4.addEdge(8, 9)
g4.addEdge(9, 8)
print "\nSSC in fourth graph "
g4.SCC();g5 = Graph (5)
g5.addEdge(0, 1)
g5.addEdge(1, 2)
g5.addEdge(2, 3)
g5.addEdge(2, 4)
g5.addEdge(3, 0)
g5.addEdge(4, 2)
print "\nSSC in fifth graph "
g5.SCC();#This code is contributed by Neelam Yadav

 

Tarjan算法查找强联通组件的程序相关推荐

  1. Tarjan算法 (强联通分量 割点 割边)

    变量解释: low 指当前节点在同一强连通分量(或环)能回溯到的dfn最小的节点 dfn 指当前节点是第几个被搜到的节点(时间戳) sta 栈 vis 是否在栈中 ans 指强连通分量的数量 top ...

  2. P3387-【模板】缩点【tarjan,强联通分量,DAGdp】

    正题 评测记录: https://www.luogu.org/recordnew/lists?uid=52918&pid=P3387 大意 一个有向图.每个点有权值,但每个值只能取一次,每条边 ...

  3. 海亮DAY8 关于Tarjan算法用于割点割边相关感受

    Tarjan 简介 Tarjan算法在求割点,割边,连通分量方面及其高效,在军事,交通,设计等方面有重要作用. 由于Tarjan算法思想并不难懂,在此不放上Tarjan算法的具体介绍. [Usaco2 ...

  4. tarjan算法求割点割边

    在上一节我们已经知道tarjan算法可以求联通图,在这里我们也运用tarjan的思想求割点与割边,首先我们先来说说割点,那么什么事割点呢,先来看一张图(a),图片来自网络 在(a)图中,我们将A点以及 ...

  5. POJ 2186 popular cow 有向图的强联通问题 Tarjan算法

    参考:http://hi.baidu.com/1093782566/blog/item/e5a0e9229913bd048b82a175.html http://www.cppblog.com/Iro ...

  6. 强联通块tarjan算法

    http://poj.org/problem?id=1236 第一问:需要几个学校存在软件,才能通过传递,使得所有的学校都有软件 用tarjan算法求出强联通分量后,将每个联通分量缩成一个点,那么问题 ...

  7. tarjan算法 割点割边强联通 算法讲解模板 自用整理

    很早就学过tarjan算法(割点割边与强联通)了,但是因为久不用老是忘,也有收藏过几篇不错的博客,但是每次需要时都要翻出那几篇太麻烦了,所以自己开篇记录方便自己的复习.图片和部分文字来源自其他博客,文 ...

  8. 『Tarjan算法 无向图的双联通分量』

    无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...

  9. Tarjan的强联通分量

    求强联通分量有很多种. <C++信息学奥赛一本通>  中讲过一个dfs求强联通分量的算法Kosdaraju,为了骗字数我就待会简单的说说.然而我们这篇文章的主体是Tarjan,所以我肯定说 ...

最新文章

  1. 什么是三极管的倒置状态及其作用!
  2. 数据存储方案-闭包表
  3. Redis多机功能之复制
  4. pytorch1.7教程实验——使用 TensorBoard 可视化模型,数据和训练
  5. Linux下open函数、read函数、write函数记录
  6. mysql导入 内存溢出_导入数据库内存溢出
  7. Reset Image Size 2
  8. 美图欣赏,转载[原文链接http://toutiao.com/a4001258776/]
  9. 安装原版Win8.1并激活
  10. 综合布线3D虚拟仿真教学实训平台
  11. 小程序 40163_微信小程序请求openid错误码40163
  12. 计算机键盘锁不了怎么办,键盘锁住了怎么解锁?键盘锁死了怎么办?
  13. JAVA-操作excel模版进行写入
  14. 前端(JS)windows命令行生成树目录结构和结构图
  15. codevs 1373 射命丸文(矩阵前缀和)
  16. 安卓指纹支付(指纹识别)
  17. window设置minio自启动时候*报错某些服务未由其他服务使用时将自动停止
  18. PCB设计指南——关于过孔
  19. [百家争鸣]LYT演讲:人文素养的必要
  20. 网卡出现“Windows 仍在设置此设备的类配置。 (代码 56)“

热门文章

  1. 开源引擎推荐—ElGameEngine 作者:trcj(http://blog.csdn.net/trcj1)
  2. 小程序和网站中无限滚动的实现
  3. HBuilderX真机调试检测不到魅族手机
  4. 详解:Oracle数据库介绍 、字符、类型、语言
  5. 计算机网络-自顶向下方法(7th) 第二章 Review Questions 英文题目+中文答案
  6. 戴尔服务器哪1顶型号好,戴尔PowerEdge R730xd新一代服务器评测
  7. Tensorflow——add_layer(添加神经层)
  8. 自然语言处理——BERT情感分类实战(一)之预处理
  9. 类和对象编程(八):指向类的指针
  10. Win10+VS2015+CUDA9.0 环境搭建