// Search for an augmenting path in the graph graf. // On success, the path data structure will include a list // that forms the augmenting path. In this case, the last // edge in the list is returned as the function value. // On failure, returns 0. edge edmonds::findpath() { vertex u,v,vp,w,wp,x,y; edge e, f; int t1, t2, t3; t1 = Util::getTime(); blossoms->clear(); for (u = 1; u <= graf->n(); u++) { state[u] = even; pEdge[u] = 0; origin[u] = u; } for (e = match->first(); e != 0; e = match->next(e)) { u = graf->left(e); v = graf->right(e); state[u] = state[v] = unreached; } UiList q(graf->m()); // list of edges to be processed in main loop for (e = 1; e <= graf->m(); e++) { if (state[graf->left(e)] == even || state[graf->right(e)] == even) q.addLast(e); } t2 = Util::getTime(); pathInitTime += (t2-t1); while (!q.empty()) { stepCount++; e = q.first(); q.removeFirst(); v = graf->left(e); vp = origin[blossoms->find(v)]; if (state[vp] != even) { v = graf->right(e); vp = origin[blossoms->find(v)]; } w = graf->mate(v,e); wp = origin[blossoms->find(w)]; if (vp == wp) continue; // skip internal edges in a blossom if (state[wp] == unreached) { // w is not contained in a blossom and is matched // so extend tree and add newly eligible edges to q x = graf->mate(w,mEdge[w]); state[w] = odd; pEdge[w] = e; state[x] = even; pEdge[x] = mEdge[w]; for (f = graf->firstAt(x); f != 0; f = graf->nextAt(x,f)) { if ((f != mEdge[x]) && !q.member(f)) q.addLast(f); } continue; } u = nca(vp,wp); if (state[wp] == even && u == 0) { // vp, wp are different trees - construct path & return x = vp; while (pEdge[x] != 0) { x = origin[blossoms->find( graf->mate(x,pEdge[x]))]; } y = wp; while (pEdge[y] != 0) { y = origin[blossoms->find( graf->mate(y,pEdge[y]))]; } e = augpath->join(augpath->reverse(path(v,x)),e); e = augpath->join(e,path(w,y)); t3 = Util::getTime(); pathFindTime += (t3-t2); return e; } else if (state[wp] == even) { // vp and wp are in same tree - collapse blossom blossomCount++; x = vp; int fu = blossoms->find(u); int fx = blossoms->find(x); while (fx != fu) { fu = blossoms->link(fx,fu); if (state[x] == odd) { bridge[x].e = e; bridge[x].v = v; for (f = graf->firstAt(x); f != 0; f = graf->nextAt(x,f)) if (!q.member(f)) q.addLast(f); } x = origin[blossoms->find( graf->mate(x,pEdge[x]))]; fx = blossoms->find(x); } y = wp; int fy = blossoms->find(y); while (fy != fu) { fu = blossoms->link(fy,fu); if (state[y] == odd) { bridge[y].e = e; bridge[y].v = w; for (f = graf->firstAt(y); f != 0; f = graf->nextAt(y,f)) if (!q.member(f)) q.addLast(f); } y = origin[blossoms->find( graf->mate(y,pEdge[y]))]; fy = blossoms->find(y); } origin[fu] = u; } } t3 = Util::getTime(); pathFindTime += (t3-t2); return 0; }
int main() { input(); nca(); //printf("%d",target1_parent[1]); }