/// Returns the ID of the neighbor that \c NId pushes to, -1 if no push was made. int PushRelabel (TPRManager &PRM, const int &NId, const TNEANet::TNodeI &NI) { int EdgeN = PRM.EdgeNum(NId); int EId = -1, NbrNId = -1, ResFlow = 0; int Cutoff = NI.GetInDeg(); if (EdgeN < Cutoff) { EId = NI.GetInEId(EdgeN); NbrNId = NI.GetInNId(EdgeN); ResFlow = PRM.Flow(EId); } else { EId = NI.GetOutEId(EdgeN - Cutoff); NbrNId = NI.GetOutNId(EdgeN - Cutoff); ResFlow = PRM.Capacity(EId) - PRM.Flow(EId); } if (ResFlow > 0 && PRM.Label(NId) - 1 == PRM.Label(NbrNId)) { if (EdgeN < Cutoff) { PushToInNbr(PRM, NId, NbrNId, EId); } else { PushToOutNbr(PRM, NId, NbrNId, EId); } return NbrNId; } if (EdgeN + 1 == NI.GetDeg()) { PRM.EdgeNum(NId) = 0; Relabel(PRM, NId, NI); } else { PRM.EdgeNum(NId)++; } return -1; }
/// Increases the label of a node \c NId to allow valid pushes to some neighbor. void Relabel (TPRManager &PRM, const int &NId, const TNEANet::TNodeI &NI) { int MaxLabel = PRM.GetMaxLabel(); int MinLabel = MaxLabel; for (int EdgeN = 0; EdgeN < NI.GetInDeg(); EdgeN++) { if (PRM.Flow(NI.GetInEId(EdgeN)) > 0) { int InLabel = PRM.Label(NI.GetInNId(EdgeN)); MinLabel = min(MinLabel, InLabel); } } for (int EdgeN = 0; EdgeN < NI.GetOutDeg(); EdgeN++) { if (PRM.Capacity(NI.GetOutEId(EdgeN)) > PRM.Flow(NI.GetOutEId(EdgeN))) { int OutLabel = PRM.Label(NI.GetOutNId(EdgeN)); MinLabel = min(MinLabel, OutLabel); } } if (MinLabel == MaxLabel) { PRM.SetLabel(NId, MaxLabel); } else { PRM.SetLabel(NId, MinLabel + 1); } }
int GetMaxFlowIntPR (PNEANet &Net, const int& SrcNId, const int& SnkNId) { IAssert(Net->IsNode(SrcNId)); IAssert(Net->IsNode(SnkNId)); if (SrcNId == SnkNId) { return 0; } TPRManager PRM(Net); int MaxLabel = PRM.GetMaxLabel(); TNEANet::TNodeI SrcNI = Net->GetNI(SrcNId); for (int EdgeN = 0; EdgeN < SrcNI.GetOutDeg(); EdgeN++) { int EId = SrcNI.GetOutEId(EdgeN); int OutNId = SrcNI.GetOutNId(EdgeN); if (OutNId != SrcNId) { int Capacity = PRM.Capacity(EId); PRM.Flow(EId) = Capacity; PRM.Excess(OutNId) = Capacity; } } GlobalRelabel(Net, PRM, SrcNId, SnkNId); PRM.SetLabel(SrcNId, MaxLabel); int RelabelCount = 1; int GRRate = Net->GetNodes(); while (PRM.HasActive()) { int NId = PRM.PopActive(); const TNEANet::TNodeI &NI = Net->GetNI(NId); int PrevLabel = MaxLabel; while (PRM.Excess(NId) > 0 && PRM.Label(NId) <= PrevLabel) { PrevLabel = PRM.Label(NId); int NbrNId = PushRelabel(PRM, NId, NI); if (NbrNId != -1 && NbrNId != SnkNId && PRM.Excess(NbrNId) > 0 && !PRM.IsActive(NbrNId)) { PRM.PushActive(NbrNId); } } if (PRM.Excess(NId) > 0 && PRM.Label(NId) < MaxLabel) { PRM.PushActive(NId); } if (RelabelCount % GRRate == 0) { GlobalRelabel(Net, PRM, SrcNId, SnkNId); } } return PRM.Excess(SnkNId); }