template <typename captype, typename tcaptype, typename flowtype> flowtype IBFSGraph<captype, tcaptype, flowtype>::maxflowClean() { node *x, *y, *xTmp, *prevTarget; arc *a, *aEnd, *aTmp; AugmentationInfo augInfo; #ifdef STATS numAugs = 0; numOrphans = 0; grownSinkTree = 0; grownSourceTree = 0; numPushes = 0; orphanArcs1 = 0; orphanArcs2 = 0; orphanArcs3 = 0; growthArcs = 0; augLenMin = 999999; augLenMax = 0; #endif // // init // orphanFirst = END_OF_ORPHANS; activeFirst1 = END_OF_LIST_NODE; activeLevel = 1; for (x=nodes; x<nodeLast; x++) { x->nextActive = NULL; x->firstSon = NULL; if (x->srcSinkCap == 0) { x->parent = NULL; } else { x->parent = PARENT_SRC_SINK; if (x->srcSinkCap > 0) { x->label = 1; SET_ACTIVE(x); } else { x->label = -1; SET_ACTIVE(x); } } } activeFirst0 = activeFirst1; activeFirst1 = END_OF_LIST_NODE; // // IBFS // prevTarget = NULL; augInfo.flowDeficit = 0; augInfo.flowExcess = 0; while (activeFirst0 != END_OF_LIST_NODE) { // // BFS level // while (activeFirst0 != END_OF_LIST_NODE) { x = activeFirst0; activeFirst0 = x->nextActive; x->nextActive = NULL; if (x->parent == NULL) { continue; } if (x->label > 0) { // // Source Tree // if (x->label != activeLevel) { SET_ACTIVE(x); continue; } #ifdef STATS grownSourceTree++; #endif aEnd = (x+1)->firstArc; for (a=x->firstArc; a != aEnd; a++) { #ifdef STATS growthArcs++; #endif if (a->rCap != 0) { y = a->head; if (y->parent == NULL) { y->label = x->label+1; y->parent = a->sister; y->nextSibling = NODE_PTR_TO_INDEX(x->firstSon); x->firstSon = y; SET_ACTIVE(y); } else if (y->label < 0) { x->nextActive = activeFirst0; activeFirst0 = x; if (prevTarget != y) { // clear deficit augInfo.remainingDeficit = 0; if (augInfo.flowDeficit != 0) { xTmp = prevTarget; for (; ; xTmp=aTmp->head) { aTmp = xTmp->parent; if (aTmp == PARENT_SRC_SINK) break; aTmp->sister->rCap += augInfo.flowDeficit; aTmp->sister_rCap = 1; aTmp->rCap -= augInfo.flowDeficit; } xTmp->srcSinkCap += augInfo.flowDeficit; augInfo.flowDeficit = 0; } } augment(a, &augInfo); prevTarget = y; if (x->parent == NULL || x->label != activeLevel) { break; } activeFirst0 = activeFirst0->nextActive; x->nextActive = NULL; a = ((x->firstArc)-1); } } } // clear excess augInfo.remainingExcess = 0; if (augInfo.flowExcess != 0) { xTmp = x; for (; ; xTmp=aTmp->head) { aTmp = xTmp->parent; if (aTmp == PARENT_SRC_SINK) break; aTmp->rCap += augInfo.flowExcess; aTmp->sister->sister_rCap = 1; aTmp->sister->rCap -= augInfo.flowExcess; } xTmp->srcSinkCap -= augInfo.flowExcess; augInfo.flowExcess = 0; } // clear deficit augInfo.remainingDeficit = 0; if (augInfo.flowDeficit != 0) { xTmp = prevTarget; for (; ; xTmp=aTmp->head) { aTmp = xTmp->parent; if (aTmp == PARENT_SRC_SINK) break; aTmp->sister->rCap += augInfo.flowDeficit; aTmp->sister_rCap = 1; aTmp->rCap -= augInfo.flowDeficit; } xTmp->srcSinkCap += augInfo.flowDeficit; augInfo.flowDeficit = 0; } prevTarget = NULL; } else { // // GROWTH SINK // if (-(x->label) != activeLevel) { SET_ACTIVE(x); continue; } #ifdef STATS grownSinkTree++; #endif aEnd = (x+1)->firstArc; for (a=x->firstArc; a != aEnd; a++) { #ifdef STATS growthArcs++; #endif if (a->sister_rCap != 0) { y = a->head; if (y->parent == NULL) { y->label = x->label-1; y->parent = a->sister; y->nextSibling = NODE_PTR_TO_INDEX(x->firstSon); x->firstSon = y; SET_ACTIVE(y); } else if (y->label > 0) { x->nextActive = activeFirst0; activeFirst0 = x; // if (prevTarget != j) // { // // clear excess // augInfo.remainingExcess = 0; // if (augInfo.flowExcess != 0) // { // i_tmp = prevTarget; // for (; ; i_tmp=a_tmp->head) // { // a_tmp = i_tmp->parent; // if (a_tmp == PARENT_SRC_SINK) break; // a_tmp->rCap += augInfo.flowExcess; // a_tmp->sister->sister_rCap = 1; // a_tmp->sister->rCap -= augInfo.flowExcess; // } // i_tmp->srcSinkCap -= augInfo.flowExcess; // augInfo.flowExcess = 0; // } // } augment(a->sister, &augInfo); prevTarget = y; if (x->parent == NULL || x->label != activeLevel) { break; } activeFirst0 = activeFirst0->nextActive; x->nextActive = NULL; a = ((x->firstArc)-1); } } } // clear excess augInfo.remainingExcess = 0; if (augInfo.flowExcess != 0) { xTmp = prevTarget; for (; ; xTmp=aTmp->head) { aTmp = xTmp->parent; if (aTmp == PARENT_SRC_SINK) break; aTmp->rCap += augInfo.flowExcess; aTmp->sister->sister_rCap = 1; aTmp->sister->rCap -= augInfo.flowExcess; } xTmp->srcSinkCap -= augInfo.flowExcess; augInfo.flowExcess = 0; } prevTarget = NULL; // clear deficit augInfo.remainingDeficit = 0; if (augInfo.flowDeficit != 0) { xTmp = x; for (; ; xTmp=aTmp->head) { aTmp = xTmp->parent; if (aTmp == PARENT_SRC_SINK) break; aTmp->sister->rCap += augInfo.flowDeficit; aTmp->sister_rCap = 1; aTmp->rCap -= augInfo.flowDeficit; } xTmp->srcSinkCap += augInfo.flowDeficit; augInfo.flowDeficit = 0; } } } // // switch to next level // activeFirst0 = activeFirst1; activeFirst1 = END_OF_LIST_NODE; activeLevel++; } return flow; }
template <typename captype, typename tcaptype, typename flowtype> flowtype IBFSGraph<captype, tcaptype, flowtype>::maxflow() { node *i, *j, *i_tmp, *prevSrc, *prevSink; arc *a, *a_end, *a_tmp; AugmentationInfo augInfo; prepareGraph(); #ifdef STATS numAugs = 0; numOrphans = 0; grownSinkTree = 0; grownSourceTree = 0; numPushes = 0; orphanArcs1 = 0; orphanArcs2 = 0; orphanArcs3 = 0; growthArcs = 0; skippedGrowth = 0; numOrphans0 = 0; numOrphans1 = 0; numOrphans2 = 0; augLenMin = 999999; augLenMax = 0; #endif // // init // orphanFirst = END_OF_ORPHANS; activeFirst1 = END_OF_LIST_NODE; activeLevel = 1; for (i=nodes; i<nodeLast; i++) { i->nextActive = NULL; i->firstSon = NULL; if (i->terminalCap == 0) { i->parent = NULL; } else { i->parent = TERMINAL; if (i->terminalCap > 0) { i->label = 1; SET_ACTIVE(i); } else { i->label = -1; SET_ACTIVE(i); } } } activeFirst0 = activeFirst1; activeFirst1 = END_OF_LIST_NODE; // // growth + augment // prevSrc = NULL; prevSink = NULL; augInfo.flowDeficit = 0; augInfo.flowExcess = 0; while (activeFirst0 != END_OF_LIST_NODE) { // // BFS level // while (activeFirst0 != END_OF_LIST_NODE) { /* i = active_src_first0; while (i->nextActive != END_OF_LIST_NODE) { if (i->parent && i->nextActive->parent && i->label > 0 && i->label != activeLevel_src && i->label != activeLevel_src+1) { i = active_src_first0; printf("flow=%d, active_label=%d, src active ", flow, activeLevel_src); while (i != END_OF_LIST_NODE) { if (i->parent && (i->nextActive == END_OF_LIST_NODE || i->nextActive->parent == NULL || i->label != i->nextActive->label)) { printf("%d ", i->label); } i = i->nextActive; } printf("\n"); break; } i = i->nextActive; } */ i = activeFirst0; activeFirst0 = i->nextActive; i->nextActive = NULL; if (i->parent == NULL) { #ifdef STATS skippedGrowth++; #endif continue; } //if (ABS(i->label) != activeLevel && // ABS(i->label) != (activeLevel+1)) //{ //#ifdef FLOATS // printf("ERROR, flow=%f, label=%d, active_label=%d\n", // flow, i->label, activeLevel); //#else // printf("ERROR, flow=%d, label=%d, active_label=%d\n", // flow, i->label, activeLevel); //#endif // exit(1); //} if (i->label > 0) { // // GROWTH SRC // if (i->label != activeLevel) { #ifdef STATS skippedGrowth++; #endif SET_ACTIVE(i); continue; } #ifdef STATS grownSourceTree++; #endif a_end = (i+1)->firstArc; for (a=i->firstArc; a != a_end; a++) { #ifdef STATS growthArcs++; #endif if (a->rCap != 0) { j = a->head; if (j->parent == NULL) { j->label = i->label+1; j->parent = a->sister; j->nextSibling = NODE_PTR_TO_INDEX(i->firstSon); i->firstSon = j; SET_ACTIVE(j); } else if (j->label < 0) { i->nextActive = activeFirst0; activeFirst0 = i; if (prevSrc != i) { augInfo.remainingExcess = 0; if (augInfo.flowExcess != 0) { i_tmp = prevSrc; for (; ; i_tmp=a_tmp->head) { a_tmp = i_tmp->parent; if (a_tmp == TERMINAL) break; a_tmp->rCap += augInfo.flowExcess; a_tmp->sister->sister_rCap = 1; a_tmp->sister->rCap -= augInfo.flowExcess; } i_tmp->terminalCap -= augInfo.flowExcess; augInfo.flowExcess = 0; } } if (prevSrc != i || prevSink != j) { augInfo.remainingDeficit = 0; if (augInfo.flowDeficit != 0) { i_tmp = prevSink; for (; ; i_tmp=a_tmp->head) { a_tmp = i_tmp->parent; if (a_tmp == TERMINAL) break; a_tmp->sister->rCap += augInfo.flowDeficit; a_tmp->sister_rCap = 1; a_tmp->rCap -= augInfo.flowDeficit; } i_tmp->terminalCap += augInfo.flowDeficit; augInfo.flowDeficit = 0; } } augment(a, &augInfo); prevSrc = i; prevSink = j; break; } } } } else { // // GROWTH SINK // if (-(i->label) != activeLevel) { #ifdef STATS skippedGrowth++; #endif SET_ACTIVE(i); continue; } #ifdef STATS grownSinkTree++; #endif a_end = (i+1)->firstArc; for (a=i->firstArc; a != a_end; a++) { #ifdef STATS growthArcs++; #endif if (a->sister_rCap != 0) { j = a->head; if (j->parent == NULL) { j->label = i->label-1; j->parent = a->sister; j->nextSibling = NODE_PTR_TO_INDEX(i->firstSon); i->firstSon = j; SET_ACTIVE(j); } else if (j->label > 0) { i->nextActive = activeFirst0; activeFirst0 = i; if (prevSink != i) { augInfo.remainingDeficit = 0; if (augInfo.flowDeficit != 0) { i_tmp = prevSink; for (; ; i_tmp=a_tmp->head) { a_tmp = i_tmp->parent; if (a_tmp == TERMINAL) break; a_tmp->sister->rCap += augInfo.flowDeficit; a_tmp->sister_rCap = 1; a_tmp->rCap -= augInfo.flowDeficit; } i_tmp->terminalCap += augInfo.flowDeficit; augInfo.flowDeficit = 0; } } if (prevSink != i || prevSrc != j) { augInfo.remainingExcess = 0; if (augInfo.flowExcess != 0) { i_tmp = prevSrc; for (; ; i_tmp=a_tmp->head) { a_tmp = i_tmp->parent; if (a_tmp == TERMINAL) break; a_tmp->rCap += augInfo.flowExcess; a_tmp->sister->sister_rCap = 1; a_tmp->sister->rCap -= augInfo.flowExcess; } i_tmp->terminalCap -= augInfo.flowExcess; augInfo.flowExcess = 0; } } augment(a->sister, &augInfo); prevSrc = j; prevSink = i; break; } } } } } augInfo.remainingDeficit = 0; if (augInfo.flowDeficit != 0) { i_tmp = prevSink; for (; ; i_tmp=a_tmp->head) { a_tmp = i_tmp->parent; if (a_tmp == TERMINAL) break; a_tmp->sister->rCap += augInfo.flowDeficit; a_tmp->sister_rCap = 1; a_tmp->rCap -= augInfo.flowDeficit; } i_tmp->terminalCap += augInfo.flowDeficit; augInfo.flowDeficit = 0; prevSink = NULL; } augInfo.remainingExcess = 0; if (augInfo.flowExcess != 0) { i_tmp = prevSrc; for (; ; i_tmp=a_tmp->head) { a_tmp = i_tmp->parent; if (a_tmp == TERMINAL) break; a_tmp->rCap += augInfo.flowExcess; a_tmp->sister->sister_rCap = 1; a_tmp->sister->rCap -= augInfo.flowExcess; } i_tmp->terminalCap -= augInfo.flowExcess; augInfo.flowExcess = 0; prevSrc = NULL; } // // switch to next level // #ifdef COUNT_RELABELS for (int k=0; k<scanIndices.size(); k++) { total++; if (scans[scanIndices[k]] <= 10) { counts[scans[scanIndices[k]]-1]++; } } #endif activeFirst0 = activeFirst1; activeFirst1 = END_OF_LIST_NODE; activeLevel++; } return flow; }
template <typename captype, typename tcaptype, typename flowtype> void IBFSGraph<captype, tcaptype, flowtype>::adoptionSink() { node *x, *y; arc *a, *aEnd; arc aTmp; int minLabel; while (orphanFirst != END_OF_ORPHANS) { x = orphanFirst; orphanFirst = x->nextOrphan; // we need PREVIOUSLY_ORPHAN vs NULL // in order to establish whether the node // has already started a "new parent" scan // while in this level or not (used in ADD_ORPHAN) x->nextOrphan = PREVIOUSLY_ORPHAN; a = x->parent; x->parent = NULL; aEnd = (x+1)->firstArc; // check for rehook if (x->label != -1) { minLabel = x->label + 1; for (; a != aEnd; a++) { #ifdef STATS orphanArcs1++; #endif y = a->head; if (a->rCap != 0 && y->parent != NULL && y->label == minLabel) { x->parent = a; x->nextSibling = NODE_PTR_TO_INDEX(y->firstSon); y->firstSon = x; break; } } } // give up on node - relabel it! if (x->parent == NULL) { minLabel = -(activeLevel+1); for (a=x->firstArc; a != aEnd; a++) { #ifdef STATS orphanArcs2++; #endif y = a->head; if (a->rCap != 0 && y->parent != NULL && y->label < 0 && y->label > minLabel) { minLabel = y->label; x->parent = a; if (minLabel == x->label) break; } } // create orphan sons for (y=x->firstSon; y; y=NODE_INDEX_TO_PTR(y->nextSibling)) { #ifdef STATS orphanArcs3++; #endif if (minLabel == x->label && y->parent != y->firstArc) { aTmp = *(y->parent); *(y->parent) = *(y->firstArc); *(y->firstArc) = aTmp; y->parent->sister->sister = y->parent; y->firstArc->sister->sister = y->firstArc; } ADD_ORPHAN_BACK(y); } x->firstSon = NULL; if (x->parent == NULL) { x->nextOrphan = NULL; } else { x->label = (minLabel-1); x->nextSibling = NODE_PTR_TO_INDEX(x->parent->head->firstSon); x->parent->head->firstSon = x; if (minLabel == -activeLevel) { SET_ACTIVE(x); } } } } }
template <typename captype, typename tcaptype, typename flowtype> void IBFSGraph<captype, tcaptype, flowtype>::adoptionSink() { node *i, *j; arc *a, *a_end; arc tmp_a; int min_label; while (orphanFirst != END_OF_ORPHANS) { // terminalCap is used as a next pointer for the orphans list i = orphanFirst; orphanFirst = i->nextOrphan; #ifdef STATS statsNumOrphans++; // if (orphanPhaseNodesHash[i-nodes] == false) // { // orphanPhaseNodesHash[i-nodes] = true; // orphanPhaseLabels[numOrphanPhaseNodes] = -(i->label); // orphanPhaseNodes[numOrphanPhaseNodes] = i; // numOrphanPhaseNodes++; // } #endif // we need PREVIOUSLY_ORPHAN vs NULL // in order to establish whether the node // has already started a "new parent" scan // while in this level or not (used in ADD_ORPHAN) i->nextOrphan = PREVIOUSLY_ORPHAN; a = i->parent; i->parent = NULL; a_end = (i+1)->firstArc; #ifdef COUNT_RELABELS if (scans[i-nodes] == 0) { scanIndices.push_back(i-nodes); } if ((scans[i-nodes]%2) == 0) { scans[i-nodes]++; } #endif // check for rehook if (i->label != -1) { min_label = i->label + 1; for (; a != a_end; a++) { #ifdef STATS orphanArcs1++; #endif j = a->head; if (a->rCap != 0 && j->parent != NULL && j->label == min_label) { i->parent = a; i->nextSibling = NODE_PTR_TO_INDEX(j->firstSon); j->firstSon = i; break; } } } // give up on node - relabel it! if (i->parent == NULL) { #ifdef COUNT_RELABELS scans[i-nodes]++; #endif min_label = -(activeLevel+1); for (a=i->firstArc; a != a_end; a++) { #ifdef STATS orphanArcs2++; #endif j = a->head; if (a->rCap != 0 && j->parent != NULL && j->label < 0 && j->label > min_label) { min_label = j->label; i->parent = a; if (min_label == i->label) break; } } for (j=i->firstSon; j; j=NODE_INDEX_TO_PTR(j->nextSibling)) { #ifdef STATS orphanArcs3++; #endif if (min_label == i->label && j->parent != j->firstArc) { tmp_a = *(j->parent); *(j->parent) = *(j->firstArc); *(j->firstArc) = tmp_a; j->parent->sister->sister = j->parent; j->firstArc->sister->sister = j->firstArc; } ADD_ORPHAN_BACK(j); } i->firstSon = NULL; if (i->parent == NULL) { i->nextOrphan = NULL; } else { i->label = (min_label-1); i->nextSibling = NODE_PTR_TO_INDEX(i->parent->head->firstSon); i->parent->head->firstSon = i; if (min_label == -activeLevel) { SET_ACTIVE(i); } } } } }