Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/match/flowMatch.cpp
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 }
 All Classes Files Functions Variables Typedefs Friends