Exemplo n.º 1
0
/// 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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
// 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;
}