public static void MainTest(string[] args) { int V1 = int.Parse(args[0]); int V2 = int.Parse(args[1]); int E = int.Parse(args[2]); int F = int.Parse(args[3]); BipartiteX b; // create random bipartite graph with V1 vertices on left side, // V2 vertices on right side, and E edges; then add F random edges Graph G = GraphGenerator.Bipartite(V1, V2, E); Console.WriteLine("Graph is {0}\n", G); b = new BipartiteX(G); BipartiteXReport(b); for (int i = 0; i < F; i++) { int v = StdRandom.Uniform(V1 + V2); int w = StdRandom.Uniform(V1 + V2); G.AddEdge(v, w); } Console.WriteLine("After adding {0} random edges", F); Console.WriteLine("Graph is {0}\n", G); b = new BipartiteX(G); BipartiteXReport(b); }
private int[] edgeTo; // edgeTo[v] = w if v-w is last edge on path to w /// <summary> /// Determines a maximum matching (and a minimum vertex cover) /// in a bipartite graph.</summary> /// <param name="G">the bipartite graph</param> /// <exception cref="ArgumentException">if <c>G</c> is not bipartite</exception> /// public BipartiteMatching(Graph G) { bipartition = new BipartiteX(G); if (!bipartition.IsBipartite) { throw new ArgumentException("graph is not bipartite"); } numVertices = G.V; // initialize empty matching mate = new int[numVertices]; for (int v = 0; v < numVertices; v++) { mate[v] = UNMATCHED; } // alternating path algorithm while (hasAugmentingPath(G)) { // find one endpoint t in alternating path int t = -1; for (int v = 0; v < numVertices; v++) { if (!IsMatched(v) && edgeTo[v] != -1) { t = v; break; } } // update the matching according to alternating path in edgeTo[] array for (int v = t; v != -1; v = edgeTo[edgeTo[v]]) { int w = edgeTo[v]; mate[v] = w; mate[w] = v; } cardinality++; } // find min vertex cover from marked[] array inMinVertexCover = new bool[numVertices]; for (int v = 0; v < numVertices; v++) { if (bipartition.Color(v) && !marked[v]) { inMinVertexCover[v] = true; } if (!bipartition.Color(v) && marked[v]) { inMinVertexCover[v] = true; } } Debug.Assert(certifySolution(G)); }
private static void BipartiteXReport(BipartiteX b) { if (b.IsBipartite) { Graph G = b.G; Console.WriteLine("Graph is bipartite"); for (int v = 0; v < G.V; v++) { Console.WriteLine(v + ": " + b.Color(v)); } } else { Console.Write("Graph has an odd-length cycle: "); foreach (int x in b.OddCycle()) { Console.Write(x + " "); } } Console.WriteLine(); }
private int[] distTo; // distTo[v] = number of edges on shortest path to v /// <summary> /// Determines a maximum matching (and a minimum vertex cover) /// in a bipartite graph.</summary> /// <param name="G">the bipartite graph</param> /// <exception cref="ArgumentException">if <c>G</c> is not bipartite</exception> /// public HopcroftKarp(Graph G) { bipartition = new BipartiteX(G); if (!bipartition.IsBipartite) { throw new ArgumentException("graph is not bipartite"); } // initialize empty matching this.V = G.V; mate = new int[V]; for (int v = 0; v < V; v++) { mate[v] = UNMATCHED; } // the call to hasAugmentingPath() provides enough info to reconstruct level graph while (hasAugmentingPath(G)) { // to be able to iterate over each adjacency list, keeping track of which // vertex in each adjacency list needs to be explored next IEnumerator <int>[] adj = new IEnumerator <int> [G.V]; for (int v = 0; v < G.V; v++) { adj[v] = G.Adj(v).GetEnumerator(); } // for each unmatched vertex s on one side of bipartition for (int s = 0; s < V; s++) { if (IsMatched(s) || !bipartition.Color(s)) { continue; // or use distTo[s] == 0 } // find augmenting path from s using nonrecursive DFS LinkedStack <int> path = new LinkedStack <int>(); path.Push(s); while (!path.IsEmpty) { int v = path.Peek(); // retreat, no more edges in level graph leaving v if (!adj[v].MoveNext()) { path.Pop(); } // advance else { // process edge v-w only if it is an edge in level graph int w = adj[v].Current; if (!isLevelGraphEdge(v, w)) { continue; } // add w to augmenting path path.Push(w); // augmenting path found: update the matching if (!IsMatched(w)) { // Console.WriteLine("augmenting path: " + toString(path)); while (!path.IsEmpty) { int x = path.Pop(); int y = path.Pop(); mate[x] = y; mate[y] = x; } cardinality++; } } } } } // also find a min vertex cover inMinVertexCover = new bool[V]; for (int v = 0; v < V; v++) { if (bipartition.Color(v) && !marked[v]) { inMinVertexCover[v] = true; } if (!bipartition.Color(v) && marked[v]) { inMinVertexCover[v] = true; } } Debug.Assert(certifySolution(G)); }