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;
}
示例#2
0
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);
				}
			}
		}
	}
}
示例#4
0
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);
				}
			}
		}
	}
}