Grafalgo
Library of useful data structures and algorithms
|
00001 // flowMatch(graf,match) - max matching on bipartite graphs 00002 // 00003 // This file contains two versions of flowMatch(graf,match), the algorithm for 00004 // computing a maximum matching in a bipartite graph using max flows. 00005 // If the first argument is an unweighted graph, a maximum size 00006 // matching is returned in match. If the first argument is a weighted 00007 // graph, a maximum weight matching is returned. 00008 // 00009 // Think about rewriting this as a class. 00010 00011 #include "stdinc.h" 00012 #include "Wgraph.h" 00013 #include "List.h" 00014 #include "Dlist.h" 00015 #include "Wflograph.h" 00016 #include "Dheap.h" 00017 #include "dinic.h" 00018 #include "lcap.h" 00019 00020 using namespace grafalgo; 00021 00022 bool findCut(const Graph&, List&); 00023 void makFlograph(const Graph&, const List&, Flograph&); 00024 00025 void flowMatch(Graph& graf, Dlist& match, int& size) { 00026 // Find a maximum size matching in the bipartite graph graf and 00027 // return it as a list of edges. 00028 Flograph fg(graf.n()+2,graf.n()+graf.m(),graf.n()+1,graf.n()+2); 00029 List cut(graf.n()); 00030 00031 if (!findCut(graf,cut)) 00032 Util::fatal("flowMatch: graph is not bipartite"); 00033 makFlograph(graf,cut,fg); 00034 00035 flow floVal; 00036 dinic(fg,floVal); 00037 size = floVal; 00038 00039 for (edge e = 1; e <= graf.m(); e++) { 00040 if (fg.f(graf.left(e),e) != 0) match.addLast(e); 00041 } 00042 } 00043 00044 // Find a maximum weight matching in the bipartite graph graf and 00045 // return it as a list of edges. 00046 void flowMatch(Wgraph& graf, Dlist& match, int& size, int& weight) { 00047 Wflograph fg(graf.n()+2,graf.n()+graf.m(),graf.n()+1,graf.n()+2); 00048 List cut(graf.n()); 00049 00050 if (!findCut(graf,cut)) 00051 Util::fatal("flowMatch: graph is not bipartite"); 00052 makFlograph(graf,cut,fg); 00053 for (edge e = 1; e <= graf.m(); e++) fg.setCost(e,-graf.weight(e)); 00054 for (edge e = graf.m()+1; e <= fg.m(); e++) fg.setCost(e,0); 00055 00056 flow flowVal; floCost flowCost; 00057 lcap(fg,flowVal,flowCost,true); 00058 size = flowVal; weight = -flowCost; 00059 00060 for (edge e = 1; e <= graf.m(); e++) { 00061 if (fg.f(graf.left(e),e) != 0) match.addLast(e); 00062 } 00063 } 00064 00065 bool findCut(const Graph& graf, List& cut) { 00066 // Return true if graf is bipartite, else false. 00067 // If graf is bipartite, return a set of vertices cut that defines 00068 // a cut that is crossed by all edges in graf. 00069 vertex u, v, w; edge e; 00070 enum stype { unreached, odd, even}; 00071 stype state[graf.n()+1]; 00072 List q(graf.n()); 00073 00074 for (u = 1; u <= graf.n(); u++) state[u] = unreached; 00075 u = 1; 00076 while (u <= graf.n()) { 00077 state[u] = even; 00078 q.addLast(u); cut.addLast(u); 00079 while (!q.empty()) { 00080 v = q.first(); q.removeFirst(); 00081 for (e = graf.firstAt(v); e!=0; e = graf.nextAt(v,e)) { 00082 w = graf.mate(v,e); 00083 if (state[w] == state[v]) return false; 00084 if (state[w] == unreached) { 00085 state[w] = state[v]==even ? odd : even; 00086 if (state[w] == even) cut.addLast(w); 00087 q.addLast(w); 00088 } 00089 } 00090 } 00091 // find next unreached vertex 00092 for (u++; u <= graf.n() && state[u] != unreached; u++) {} 00093 } 00094 return true; 00095 } 00096 00097 // Create Flograph corresponding to graf. Do this, so that corresponding 00098 // edges have same edge numbers in fg and graf. 00099 void makFlograph(const Graph& graf, const List& cut, Flograph& fg) { 00100 for (edge e = 1; e <= graf.m(); e++) { 00101 vertex u; 00102 if (cut.member(graf.left(e))) u = graf.left(e); 00103 else u = graf.right(e); 00104 vertex v = graf.mate(u,e); 00105 edge ee = fg.join(u,v); 00106 fg.setCapacity(ee,1); 00107 } 00108 for (vertex u = 1; u <= graf.n(); u++) { 00109 edge e; 00110 if (cut.member(u)) e = fg.join(fg.src(),u); 00111 else e = fg.join(u,fg.snk()); 00112 fg.setCapacity(e,1); 00113 } 00114 }