// compute residual path from source to sink using breadth first search // This way the Edmonds & Karp-Algorithm ensures that the shortest path // is chosen in each iteration and thus ensures polynomial complexity. public override List <int> ComputeResidualPath(FlowGraph network) { int V = network.Nodes(); bool[] visited = new bool[V]; // marks already visited nodes. int[] pred = new int[V]; // marks the predecessor of the // current node for the output path // initialize for (int v = 0; v < V; v++) { visited[v] = false; } for (int v = 0; v < V; v++) { pred[v] = -1; } visited[network.Source] = true; Queue <int> nextNodes = new Queue <int>(); nextNodes.Enqueue(network.Source); while (nextNodes.Count > 0) { int v = nextNodes.Dequeue(); foreach (Edge edge in network.Edges(v)) { // we are only interested in paths with nonzero weights. if ((edge.Weight() > 0) && !visited[edge.To()]) { if (edge.To() != network.Target) { // If we have not yet reached the target, continue the // search. visited[edge.To()] = true; pred[edge.To()] = v; nextNodes.Enqueue(edge.To()); } else { // If we have reached the target, we extract the path. List <int> path = new List <int>(); path.Add(network.Target); while (v != network.Source) { path.Add(v); v = pred[v]; } path.Add(network.Source); // ... and return it path.Reverse(); return(path); } } } } // no path found, return null return(null); }
// Computes a bipartite matching in the given graph with the given partition of nodes. // The partition is given in form of a boolean array as returned by the Partition // function. public static List <Edge> Matching(UndirectedGraph.Graph graph, bool[] partition) { List <Edge> matching = new List <Edge>(); //TODO: Implement DirectedWeightedGraph.Graph g = new DirectedWeightedGraph.Graph(graph.Nodes() + 2); int s = 0; int t = g.Nodes() - 1; for (int i = 0; i < graph.Nodes(); i++) { List <int> nodes = graph.AllNodes(i); for (int j = 0; j < nodes.Count; j++) { g.AddEdge(i + 1, nodes[j], 1); if (partition[i]) { g.AddEdge(i + 1, t, 1); } else { g.AddEdge(s, i + 1, 1); } } } FlowGraph network = new FlowGraph(g, s, t); FlowOptimizer optimizer = new EdmondsKarp.EdmondsKarp(); //optimizer.InteractiveOptimumFlow(network); optimizer.OptimumFlow(network); network.ComputeFlow(); for (int v = 1; v < network.Nodes() - 1; v++) { foreach (Edge edge in network.Edges(v)) { if (edge.To() != s && edge.From() != t && edge.Weight() > 0) { matching.Add(edge); break; } } } // Display the optimum flow //System.Console.WriteLine("Flow is " + network.ComputeFlow()); return(matching); }