深度优先搜索检测有向图有无环路算法
2015-01-30 20:48
441 查看
给定有向图 G = (V, E),需要判断该图中是否存在环路(Cycle)。例如,下面的图 G 中包含 4 个顶点和 6 条边。
实际上,上图中存在 3 个环路:0->2->0, 0->1->2->0, 3->3。
深度优先搜索(DFS:Depth-First Search)可以用于检测图中是否存在环。DFS 会对一个连通的图构造一颗树,如果在构造树的过程中出现反向边(Back Edge),则认为图中存在环路。
对于非连通图,可以对图中的不同部分分别进行 DFS 构造树结构,对于每棵树分别检测反向边的存在。
在 DFS 对图进行遍历时,将遍历过的顶点放入递归栈中,如果新遍历的顶点已经存在于递归栈中,则说明存在一个反向边,即存在一个环。
本篇文章《DFS 检测有向图有无环算法》由 Dennis Gao 发表自博客园,未经作者本人同意禁止任何形式的转载,任何自动或人为的爬虫转载行为均为耍流氓。
实际上,上图中存在 3 个环路:0->2->0, 0->1->2->0, 3->3。
深度优先搜索(DFS:Depth-First Search)可以用于检测图中是否存在环。DFS 会对一个连通的图构造一颗树,如果在构造树的过程中出现反向边(Back Edge),则认为图中存在环路。
对于非连通图,可以对图中的不同部分分别进行 DFS 构造树结构,对于每棵树分别检测反向边的存在。
在 DFS 对图进行遍历时,将遍历过的顶点放入递归栈中,如果新遍历的顶点已经存在于递归栈中,则说明存在一个反向边,即存在一个环。
using System; using System.Collections.Generic; using System.Linq; namespace GraphAlgorithmTesting { class Program { static void Main(string[] args) { Graph g = new Graph(6); g.AddEdge(0, 1, 16); g.AddEdge(0, 2, 13); g.AddEdge(1, 2, 10); g.AddEdge(1, 3, 12); g.AddEdge(2, 1, 4); g.AddEdge(2, 4, 14); //g.AddEdge(3, 2, 9); g.AddEdge(3, 5, 20); //g.AddEdge(4, 3, 7); //g.AddEdge(4, 5, 4); Console.WriteLine(); Console.WriteLine("Graph Vertex Count : {0}", g.VertexCount); Console.WriteLine("Graph Edge Count : {0}", g.EdgeCount); Console.WriteLine(); Console.WriteLine("Is there cycle in graph: {0}", g.HasCycle()); Console.ReadKey(); } class Edge { public Edge(int begin, int end, int weight) { this.Begin = begin; this.End = end; this.Weight = weight; } public int Begin { get; private set; } public int End { get; private set; } public int Weight { get; private set; } public override string ToString() { return string.Format( "Begin[{0}], End[{1}], Weight[{2}]", Begin, End, Weight); } } class Graph { private Dictionary<int, List<Edge>> _adjacentEdges = new Dictionary<int, List<Edge>>(); public Graph(int vertexCount) { this.VertexCount = vertexCount; } public int VertexCount { get; private set; } public IEnumerable<int> Vertices { get { return _adjacentEdges.Keys; } } public IEnumerable<Edge> Edges { get { return _adjacentEdges.Values.SelectMany(e => e); } } public int EdgeCount { get { return this.Edges.Count(); } } public void AddEdge(int begin, int end, int weight) { if (!_adjacentEdges.ContainsKey(begin)) { var edges = new List<Edge>(); _adjacentEdges.Add(begin, edges); } _adjacentEdges[begin].Add(new Edge(begin, end, weight)); } public bool HasCycle() { // mark all the vertices as not visited // and not part of recursion stack bool[] visited = new bool[VertexCount]; bool[] recursionStack = new bool[VertexCount]; for (int i = 0; i < VertexCount; i++) { visited[i] = false; recursionStack[i] = false; } // call the recursive helper function to // detect cycle in different DFS trees for (int i = 0; i < VertexCount; i++) if (CheckCyclic(i, visited, recursionStack)) return true; return false; } private bool CheckCyclic(int v, bool[] visited, bool[] recursionStack) { if (!visited[v]) { // mark the current node as visited // and part of recursion stack visited[v] = true; recursionStack[v] = true; // recur for all the vertices adjacent to this vertex if (_adjacentEdges.ContainsKey(v)) { foreach (var edge in _adjacentEdges[v]) { if (!visited[edge.End] && CheckCyclic(edge.End, visited, recursionStack)) return true; else if (recursionStack[edge.End]) return true; } } } // remove the vertex from recursion stack recursionStack[v] = false; return false; } } } }
本篇文章《DFS 检测有向图有无环算法》由 Dennis Gao 发表自博客园,未经作者本人同意禁止任何形式的转载,任何自动或人为的爬虫转载行为均为耍流氓。
相关文章推荐
- 【游戏编程】AI-迷宫寻路算法-深度优先搜索和广度优先搜索
- 图基本算法 图搜索(广度优先、深度优先)
- 机试算法讲解: 第46题 深度优先搜索之能否逃出魔掌
- 该深度优先搜索算法查找钥匙的程序之问题~~
- Num 36 : ZOJ 2100 [ 深度优先搜索算法 ] [ 回溯 ]
- 深度优先用法之检测有无环
- 图基本算法 图搜索基于邻接表的(广度优先、深度优先)
- 算法之深度优先搜索和广度优先搜索
- (算法入门)基本图论-深度优先搜索之JAVA实现
- 深度优先搜索1-寻路问题(算法基础 第6周)
- 算法起步之深度优先搜索
- 【算法——02】图的遍历——BFS广度优先搜索、DFS深度优先搜索
- Union-Find 检测无向图有无环路算法
- 栈:深度优先搜索与回溯算法求解迷宫
- 【Python排序搜索基本算法】之深度优先搜索、广度优先搜索、拓扑排序、强联通&Kosaraju算法
- 算法 DFS深度优先搜索
- AI-迷宫寻路算法-深度优先搜索和广度优先搜索
- 算法——基本的图算法:广度优先搜索、深度优先搜索
- 深度优先搜索1-城堡问题(算法基础 第6周)
- Num 35 : HDOJ : 1241 Oil Deposits [ 深度优先搜索算法 ] [ 非回溯 ][ 图论 ]