private bool dfs(DiGraphVertex <T> current, HashSet <T> visited, HashSet <T> visiting) { visiting.Add(current.Value); foreach (var edge in current.OutEdges) { //if we encountered a visiting vertex again //then their is a cycle if (visiting.Contains(edge.Value)) { return(true); } if (visited.Contains(edge.Value)) { continue; } if (dfs(edge, visited, visiting)) { return(true); } } visiting.Remove(current.Value); visited.Add(current.Value); return(false); }
/// <summary> /// Do a depth first search to find Strongly Connected by keeping track of /// discovery nodes and checking for back edges using low/discovery time maps /// </summary> /// <param name="currentVertex"></param> /// <param name="result"></param> /// <param name="discovery"></param> /// <param name="discoveryTimeMap"></param> /// <param name="lowTimeMap"></param> /// <param name="parent"></param> /// <param name="discoveryTime"></param> /// <returns></returns> private void DFS(DiGraphVertex <T> currentVertex, List <List <T> > result, Dictionary <T, int> discoveryTimeMap, Dictionary <T, int> lowTimeMap, Stack <T> pathStack, HashSet <T> pathStackMap, ref int discoveryTime) { discoveryTimeMap.Add(currentVertex.Value, discoveryTime); lowTimeMap.Add(currentVertex.Value, discoveryTime); pathStack.Push(currentVertex.Value); pathStackMap.Add(currentVertex.Value); foreach (var edge in currentVertex.OutEdges) { if (!discoveryTimeMap.ContainsKey(edge.Value)) { discoveryTime++; DFS(edge, result, discoveryTimeMap, lowTimeMap, pathStack, pathStackMap, ref discoveryTime); //propogate lowTime index of neighbour so that ancestors can see it in DFS lowTimeMap[currentVertex.Value] = Math.Min(lowTimeMap[currentVertex.Value], lowTimeMap[edge.Value]); } else { //ignore cross edges //even if edge vertex was already visisted //update this so that ancestors can see it if (pathStackMap.Contains(edge.Value)) { lowTimeMap[currentVertex.Value] = Math.Min(lowTimeMap[currentVertex.Value], discoveryTimeMap[edge.Value]); } } } //if low is high this means we reached head of the DFS tree with strong connectivity //now print items in the stack if (lowTimeMap[currentVertex.Value] == discoveryTimeMap[currentVertex.Value]) { var strongConnected = new List <T>(); while (!pathStack.Peek().Equals(currentVertex.Value)) { var vertex = pathStack.Pop(); strongConnected.Add(vertex); pathStackMap.Remove(vertex); } //add current vertex var finalVertex = pathStack.Pop(); strongConnected.Add(finalVertex); pathStackMap.Remove(finalVertex); result.Add(strongConnected); } }
/// <summary> /// Do a depth first search /// </summary> /// <param name="vertex"></param> /// <param name="visited"></param> /// <param name="pathStack"></param> private void dfs(DiGraphVertex <T> vertex, HashSet <T> visited, Stack <T> pathStack) { visited.Add(vertex.Value); foreach (var edge in vertex.OutEdges) { if (!visited.Contains(edge.Value)) { dfs(edge, visited, pathStack); } } //add vertex to stack after all edges are visited pathStack.Push(vertex.Value); }
/// <summary> /// In step two we just add all reachable nodes to result (connected componant) /// </summary> /// <param name="currentVertex"></param> /// <param name="visited"></param> /// <param name="finishStack"></param> /// <param name="result"></param> /// <returns></returns> private List <T> KosarajuStep2(DiGraphVertex <T> currentVertex, HashSet <T> visited, Stack <T> finishStack, List <T> result) { visited.Add(currentVertex.Value); result.Add(currentVertex.Value); foreach (var edge in currentVertex.OutEdges) { if (!visited.Contains(edge.Value)) { KosarajuStep2(edge, visited, finishStack, result); } } return(result); }
/// <summary> /// Just do a DFS keeping track on finish Stack of Vertices /// </summary> /// <param name="currentVertex"></param> /// <param name="visited"></param> /// <param name="finishStack"></param> private void KosarajuStep1(DiGraphVertex <T> currentVertex, HashSet <T> visited, Stack <T> finishStack) { visited.Add(currentVertex.Value); foreach (var edge in currentVertex.OutEdges) { if (!visited.Contains(edge.Value)) { KosarajuStep1(edge, visited, finishStack); } } //finished visiting, so add to stack finishStack.Push(currentVertex.Value); }