Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/match/faltPath.cpp
00001 #include "faltPath.h"
00002 
00003 using namespace grafalgo;
00004 
00005 faltPath::faltPath(Graph& graf1, Dlist& match1, int& size) : graf(&graf1), match(&match1) {
00006 // Find a maximum size matching in the bipartite graph graf and
00007 // return it as a list of edges. Return the number of edges
00008 // in the mapping in size.
00009         int sNum; vertex u, v; edge e;
00010 
00011         state = new stype[graf->n()+1]; visit = new int[graf->n()+1];
00012         mEdge = new edge[graf->n()+1]; pEdge = new edge[graf->n()+1];
00013         free = new Dlist(graf->n()); leaves = new List(graf->n());
00014 
00015         match->clear(); size = 0;
00016         for (u = 1; u <= graf->n(); u++) { visit[u] = 0; mEdge[u] = 0; }
00017         // Build initial matching
00018         for (e = graf->first(); e != 0; e = graf->next(e)) {
00019                 u = graf->left(e); v = graf->right(e);
00020                 if (mEdge[u] == 0 && mEdge[v] == 0) {
00021                         match->addLast(e); mEdge[u] = mEdge[v] = e; size++;
00022                 }
00023         }
00024         for (u = 1; u <= graf->n(); u++) {
00025                 if (mEdge[u] == 0) free->addLast(u);
00026         }
00027         
00028         sNum = 0;
00029         while((e = findPath()) != 0) { augment(e); size++; }
00030 
00031         delete [] state; delete [] visit; delete [] mEdge;
00032         delete [] pEdge; delete free; delete leaves;
00033 }
00034 
00035 // Modify the matching by augmenting along the path defined by
00036 // the edge e and the pEdge pointers.
00037 void faltPath::augment(edge e) {
00038         vertex u, v; edge ee;
00039 
00040         u = graf->left(e);
00041         while (pEdge[u] != 0) {
00042                 ee = pEdge[u]; match->remove(ee); v = graf->mate(u,ee);
00043                 ee = pEdge[v]; match->addLast(ee); u = graf->mate(v,ee); 
00044                 mEdge[u] = mEdge[v] = ee;
00045         }
00046         free->remove(u);
00047         u = graf->right(e);
00048         while (pEdge[u] != 0) {
00049                 ee = pEdge[u]; match->remove(ee); v = graf->mate(u,ee);
00050                 ee = pEdge[v]; match->addLast(ee); u = graf->mate(v,ee); 
00051                 mEdge[u] = mEdge[v] = ee;
00052         }
00053         free->remove(u); match->addLast(e);
00054         mEdge[graf->left(e)] = mEdge[graf->right(e)] = e;
00055 }
00056 
00057 edge faltPath::findPath() {
00058 // Search for an augmenting path in the bipartite graph graf.
00059 // Return the edge that joins two separate trees in the forest
00060 // defined by pEdge. This edge, together with the paths
00061 // to the tree roots is an augmenting path. SNum is the
00062 // index of the current search.
00063         vertex u; edge e;
00064 
00065         sNum++;
00066         for (u = free->first(); u != 0; u = free->next(u)) {
00067                 visit[u] = sNum; state[u] = even; pEdge[u] = 0;
00068         }
00069         leaves->clear();
00070         for (u = free->first(); u != 0; u = free->next(u)) {
00071                 if ((e = expand(u)) != 0) return e;
00072         }
00073         while (!leaves->empty()) {
00074                 u = leaves->first(); leaves->removeFirst();
00075                 if ((e = expand(u)) != 0) return e;
00076         }
00077         return 0;
00078 }
00079 
00080 // Expand the forest at vertex v. If we find an edge connecting
00081 // to another tree, return it.
00082 edge faltPath::expand(vertex v) {
00083         vertex w, x, y; edge e;
00084 
00085         for (e = graf->firstAt(v); e != 0; e = graf->nextAt(v,e)) {
00086                 if (e == mEdge[v]) continue;
00087                 w = graf->mate(v,e);
00088                 if (visit[w] < sNum) {
00089                         x = graf->mate(w,mEdge[w]);
00090                         visit[w] = visit[x] = sNum;
00091                         state[w] = odd; pEdge[w] = e;
00092                         state[x] = even; pEdge[x] = mEdge[x];
00093                         leaves->addLast(x);
00094                 } else if (state[w] == even) {
00095                         for (x = w; pEdge[x] != 0; x = graf->mate(x,pEdge[x])){}
00096                         for (y = v; pEdge[y] != 0; y = graf->mate(y,pEdge[y])){}
00097                         if (x == y) Util::fatal("findPath: graph not bipartite");
00098                         return e;
00099                 } 
00100         }
00101         return 0;
00102 }
 All Classes Files Functions Variables Typedefs Friends