Grafalgo
Library of useful data structures and algorithms
|
00001 #include "altPath.h" 00002 00003 using namespace grafalgo; 00004 00005 // Find a maximum size matching in the bipartite graph graf and 00006 // return it as a list of edges. Return the number of edges 00007 // in the matching in size. 00008 altPath::altPath(Graph& graf1, Dlist& match1, int& size) 00009 : graf(&graf1), match(&match1) { 00010 pEdge = new edge[graf->n()+1]; 00011 00012 edge e; 00013 size = 0; 00014 while((e = findPath()) != 0) { augment(e); size++; } 00015 00016 delete [] pEdge; 00017 } 00018 00019 // Modify the matching by augmenting along the path defined by 00020 // the edge e and the pEdge pointers. 00021 void altPath::augment(edge e) { 00022 vertex u; edge ee; 00023 00024 u = graf->left(e); 00025 while (pEdge[u] != 0) { 00026 ee = pEdge[u]; match->remove(ee); u = graf->mate(u,ee); 00027 ee = pEdge[u]; match->addLast(ee); u = graf->mate(u,ee); 00028 } 00029 u = graf->right(e); 00030 while (pEdge[u] != 0) { 00031 ee = pEdge[u]; match->remove(ee); u = graf->mate(u,ee); 00032 ee = pEdge[u]; match->addLast(ee); u = graf->mate(u,ee); 00033 } 00034 match->addLast(e); 00035 } 00036 00037 // Search for an augmenting path in the bipartite graph graf. 00038 // Return the edge that joins two separate trees in the forest 00039 // defined by pEdge. This edge, together with the paths 00040 // to the tree roots is an augmenting path. 00041 // 00042 edge altPath::findPath() { 00043 vertex u,v,w,x,y; edge e, f; 00044 enum stype { unreached, odd, even }; 00045 stype state[graf->n()+1]; 00046 edge mEdge[graf->n()+1]; // mEdge[u] = matching edge incident to u 00047 00048 for (u = 1; u <= graf->n(); u++) { 00049 state[u] = even; mEdge[u] = pEdge[u] = 0; 00050 } 00051 00052 for (e = match->first(); e != 0; e = match->next(e)) { 00053 u = graf->left(e); v = graf->right(e); 00054 state[u] = state[v] = unreached; 00055 mEdge[u] = mEdge[v] = e; 00056 } 00057 List q(graf->m()); 00058 for (e = graf->first(); e != 0; e = graf->next(e)) { 00059 if (state[graf->left(e)] == even || 00060 state[graf->right(e)] == even) 00061 q.addLast(e); 00062 } 00063 00064 while (!q.empty()) { 00065 e = q.first(); q.removeFirst(); 00066 v = (state[graf->left(e)] == even ? 00067 graf->left(e) : graf->right(e)); 00068 w = graf->mate(v,e); 00069 if (state[w] == unreached && mEdge[w] != 0) { 00070 x = graf->mate(w,mEdge[w]); 00071 state[w] = odd; pEdge[w] = e; 00072 state[x] = even; pEdge[x] = mEdge[x]; 00073 for (f = graf->firstAt(x); f != 0; 00074 f = graf->nextAt(x,f)) { 00075 if ((f != mEdge[x]) && !q.member(f)) 00076 q.addLast(f); 00077 } 00078 } else if (state[w] == even) { 00079 for (x = w; pEdge[x] != 0; x = graf->mate(x,pEdge[x])){} 00080 for (y = v; pEdge[y] != 0; y = graf->mate(y,pEdge[y])){} 00081 if (x == y) Util::fatal("findpath: graph not bipartite"); 00082 return e; 00083 } 00084 } 00085 return 0; 00086 }