/// Returns the amount the flow can be augmented over the paths, 0 if no path can be found. ##TSnap::FindAugV int FindAugV (const PNEANet &Net, const int& CapIndex, TIntV &Flow, TIntQ &FwdNodeQ, TIntH &PredEdgeH, TIntQ &BwdNodeQ, TIntH &SuccEdgeH, TIntV &MidToSrcAugV, TIntV &MidToSnkAugV, const int& SrcNId, const int& SnkNId) { int MidPtNId = IntFlowBiDBFS(Net, CapIndex, Flow, FwdNodeQ, PredEdgeH, BwdNodeQ, SuccEdgeH, SrcNId, SnkNId); if (MidPtNId == -1) { return 0; } int MinAug = TInt::Mx, NId = MidPtNId, AugFlow = 0; // Build the path from the midpoint back to the source by tracing through the PredEdgeH for (int EId = PredEdgeH.GetDat(NId); NId != SrcNId; EId = PredEdgeH.GetDat(NId)) { MidToSrcAugV.Add(EId); const TNEANet::TEdgeI &EI = Net->GetEI(EId); if (EI.GetSrcNId() == NId) { NId = EI.GetDstNId(); AugFlow = Flow[EId]; } else { NId = EI.GetSrcNId(); AugFlow = Net->GetIntAttrIndDatE(EId, CapIndex) - Flow[EId]; } if (AugFlow < MinAug) { MinAug = AugFlow; } } NId = MidPtNId; // Build the path from the midpoint back to the sink by tracing through the SuccEdgeH for (int EId = SuccEdgeH.GetDat(NId); NId != SnkNId; EId = SuccEdgeH.GetDat(NId)) { MidToSnkAugV.Add(EId); const TNEANet::TEdgeI &EI = Net->GetEI(EId); if (EI.GetDstNId() == NId) { NId = EI.GetSrcNId(); AugFlow = Flow[EId]; } else { NId = EI.GetDstNId(); AugFlow = Net->GetIntAttrIndDatE(EId, CapIndex) - Flow[EId]; } if (AugFlow < MinAug) { MinAug = AugFlow; } } return MinAug; }
int GetMaxFlowIntEK (PNEANet &Net, const int &SrcNId, const int &SnkNId) { IAssert(Net->IsNode(SrcNId)); IAssert(Net->IsNode(SnkNId)); if (SrcNId == SnkNId) { return 0; } int CapIndex = Net->GetIntAttrIndE(CapAttrName); TIntV Flow(Net->GetMxEId()); // Initialize flow values to 0, and make sure capacities are nonnegative for (TNEANet::TEdgeI EI = Net->BegEI(); EI != Net->EndEI(); EI++) { IAssert(Net->GetIntAttrIndDatE(EI, CapIndex) >= 0); Flow[EI.GetId()] = 0; } // Return 0 if user attempts to flow from a node to itself. if (SrcNId == SnkNId) { return 0; } int MaxFlow = 0, MinAug, CurNId; while (true) { TIntV MidToSrcAugV; TIntV MidToSnkAugV; TIntQ FwdNodeQ; TIntQ BwdNodeQ; TIntH PredEdgeH; TIntH SuccEdgeH; MinAug = FindAugV(Net, CapIndex, Flow, FwdNodeQ, PredEdgeH, BwdNodeQ, SuccEdgeH, MidToSrcAugV, MidToSnkAugV, SrcNId, SnkNId); if (MinAug == 0) { break; } MaxFlow += MinAug; CurNId = SrcNId; for (int i = MidToSrcAugV.Len() - 1; i >= 0; i--) { int NextEId = MidToSrcAugV[i]; const TNEANet::TEdgeI &EI = Net->GetEI(NextEId); if (EI.GetSrcNId() == CurNId) { Flow[NextEId] += MinAug; CurNId = EI.GetDstNId(); } else { Flow[NextEId] -= MinAug; CurNId = EI.GetSrcNId(); } } for (int i = 0; i < MidToSnkAugV.Len(); i++) { int NextEId = MidToSnkAugV[i]; const TNEANet::TEdgeI &EI = Net->GetEI(NextEId); if (EI.GetSrcNId() == CurNId) { Flow[NextEId] += MinAug; CurNId = EI.GetDstNId(); } else { Flow[NextEId] -= MinAug; CurNId = EI.GetSrcNId(); } } } return MaxFlow; }
// Returns the NId where the two directions of search meet up, or -1 if no augmenting path exists. ##TSnap::IntFlowBiDBFS int IntFlowBiDBFS (const PNEANet &Net, const int& CapIndex, TIntV &Flow, TIntQ &FwdNodeQ, TIntH &PredEdgeH, TIntQ &BwdNodeQ, TIntH &SuccEdgeH, const int& SrcNId, const int& SnkNId) { FwdNodeQ.Push(SrcNId); PredEdgeH.AddDat(SrcNId, -1); BwdNodeQ.Push(SnkNId); SuccEdgeH.AddDat(SnkNId, -1); while (!FwdNodeQ.Empty() && !BwdNodeQ.Empty()) { // Forward search const TNEANet::TNodeI &FwdNI = Net->GetNI(FwdNodeQ.Top()); FwdNodeQ.Pop(); // Check all edges that point into the current node for those over which flow can be returned. for (int EdgeN = 0; EdgeN < FwdNI.GetInDeg(); EdgeN++) { int NextNId = FwdNI.GetInNId(EdgeN); int NextEId = FwdNI.GetInEId(EdgeN); if (!PredEdgeH.IsKey(NextNId) && Flow[NextEId] > 0) { PredEdgeH.AddDat(NextNId, NextEId); if (SuccEdgeH.IsKey(NextNId)) { return NextNId; } FwdNodeQ.Push(NextNId); } } // Check all edges that point out of the current node for those over which flow can be added. for (int EdgeN = 0; EdgeN < FwdNI.GetOutDeg(); EdgeN++) { int NextNId = FwdNI.GetOutNId(EdgeN); int NextEId = FwdNI.GetOutEId(EdgeN); if (!PredEdgeH.IsKey(NextNId) && Net->GetIntAttrIndDatE(NextEId, CapIndex) > Flow[NextEId]) { PredEdgeH.AddDat(NextNId, NextEId); if (SuccEdgeH.IsKey(NextNId)) { return NextNId; } FwdNodeQ.Push(NextNId); } } // Backward search const TNEANet::TNodeI &BwdNI = Net->GetNI(BwdNodeQ.Top()); BwdNodeQ.Pop(); // Check all edges that point out of the current node for those over which flow can be returned. for (int EdgeN = 0; EdgeN < BwdNI.GetOutDeg(); EdgeN++) { int PrevNId = BwdNI.GetOutNId(EdgeN); int PrevEId = BwdNI.GetOutEId(EdgeN); if (!SuccEdgeH.IsKey(PrevNId) && Flow[PrevEId] > 0) { SuccEdgeH.AddDat(PrevNId, PrevEId); if (PredEdgeH.IsKey(PrevNId)) { return PrevNId; } BwdNodeQ.Push(PrevNId); } } // Check all edges that point into the current node for those over which flow can be added. for (int EdgeN = 0; EdgeN < BwdNI.GetInDeg(); EdgeN++) { int PrevNId = BwdNI.GetInNId(EdgeN); int PrevEId = BwdNI.GetInEId(EdgeN); if (!SuccEdgeH.IsKey(PrevNId) && Net->GetIntAttrIndDatE(PrevEId, CapIndex) > Flow[PrevEId]) { SuccEdgeH.AddDat(PrevNId, PrevEId); if (PredEdgeH.IsKey(PrevNId)) { return PrevNId; } BwdNodeQ.Push(PrevNId); } } } return -1; }