/// <summary> /// Recursive DFS subroutine used by Ford fulkerson's algorithm /// </summary> /// <param name="vertexId"></param> /// <param name="endId"></param> /// <param name="backtrack"></param> /// <returns></returns> private bool DFS(string vertexId, string endId, Dictionary <string, string> backtrack) { if (!string.IsNullOrEmpty(vertexId)) { // Check Error condition if (vertexId == endId) { //We have found a path return(true); } else { GraphVertex currentVertex = Graph.AllVertices[vertexId]; foreach (GraphVertex neighbour in currentVertex.Neighbours) { string edgeId = currentVertex.Id + "#" + neighbour.Id; if (!backtrack.ContainsKey(neighbour.Id) && Graph.EdgeWeights[edgeId] > 0) { backtrack[neighbour.Id] = currentVertex.Id; if (DFS(neighbour.Id, endId, backtrack)) { return(true); } } } } } return(false); }
/// <summary> /// Gets all the vertices that can be reached from the source /// We can do BFS to get this. /// </summary> /// <param name="graph">graph object</param> /// <param name="startId">id of the source vertex</param> /// <returns></returns> private Dictionary <GraphVertex, bool> GetAllVerticesThatCanBeReachedFromSrc(Graph graph, string startId) { Dictionary <GraphVertex, bool> setOfVerticesFromSource = new Dictionary <GraphVertex, bool>(); //Do a BFS to get all the vertices that can be reached from the source Queue <GraphVertex> queue = new Queue <GraphVertex>(); GraphVertex source = graph.AllVertices[startId]; queue.Enqueue(source); setOfVerticesFromSource[source] = true; while (queue.Count > 0) { GraphVertex vertex = queue.Dequeue(); foreach (GraphVertex neighbour in vertex.Neighbours) { if (graph.EdgeWeights[vertex.Id + "#" + neighbour.Id] != 0 && !setOfVerticesFromSource.ContainsKey(neighbour)) { // Edges with flow 0 should not be considered // vertices in setOfVerticesFromSource keeps track of the visited vertices setOfVerticesFromSource[neighbour] = true; queue.Enqueue(neighbour); } } } return(setOfVerticesFromSource); }
/// <summary> /// Do the BFS and get the augmented path and return the current flow in that path /// </summary> /// <param name="graph">graph object</param> /// <param name="startId">source in the graph</param> /// <param name="endId">sink in the graph</param> /// <returns>current flow in that path</returns> public int BFS(Graph graph, string startId, string endId) { Dictionary <string, string> parentDict = new Dictionary <string, string>(); Queue <GraphVertex> queue = new Queue <GraphVertex>(); queue.Enqueue(graph.AllVertices[startId]); parentDict[startId] = string.Empty; while (queue.Count > 0) { GraphVertex vertex = queue.Dequeue(); if (vertex.Id == endId) { // found the augmented path and get the current flow return(GetTheFlowInCurrentPath(graph, parentDict, startId, endId)); } foreach (GraphVertex neighbour in vertex.Neighbours) { if (!parentDict.ContainsKey(neighbour.Id) && graph.EdgeWeights[vertex.Id + "#" + neighbour.Id] != 0) { // the neighbour should not have been visited and the weight of the edge should not be 0 queue.Enqueue(neighbour); parentDict[neighbour.Id] = vertex.Id; } } } return(-1); }
/// <summary> /// Add a weighted directed edge /// </summary> /// <param name="startId"></param> /// <param name="endId"></param> /// <param name="weight"></param> public void AddEdge(string startId, string endId, int weight) { if (!AllVertices.ContainsKey(startId)) { AllVertices[startId] = new GraphVertex(startId); } if (!AllVertices.ContainsKey(endId)) { AllVertices[endId] = new GraphVertex(endId); } AllVertices[startId].Neighbours.Add(AllVertices[endId]); EdgeWeights[startId + "#" + endId] = weight; }