Grafalgo
Library of useful data structures and algorithms
|
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 }