/// <summary> /// Wyznacza ścieżkę powiekszającą o maksymalnej przepustowości spośród najkrótszych ścieżek /// </summary> /// <param name="g">Graf rezydualny</param> /// <param name="s">Wierzchołek źródłowy</param> /// <param name="t">Wierzchołek docelowy</param> /// <returns> /// Krotka (augmentingValue, augmentingFlow) składająca się z przepustowości wyznaczonej ścieżki /// i grafu opisującego tą ścieżkę /// </returns> /// <remarks> /// Jeśli ścieżka powiększająca nie istnieje, to zwracana jest krotka (0.0,null).<para/> /// Jeśli graf g jest typu <see cref="AdjacencyMatrixGraph"/> to wyznaczona ścieżka powiększająca p jest typu /// <see cref="AdjacencyListsGraph{HashTableAdjacencyList}"/>, /// w przeciwnym przypadku ścieżka p jest takiego samego typu jak graf g. /// </remarks> /// <seealso cref="MaxFlowGraphExtender"/> /// <seealso cref="ASD.Graphs"/> public static (double augmentingValue, Graph augmentingFlow) BFMaxPath(this Graph g, int s, int t) { var pi = new PathsInfo[g.VerticesCount]; var steps = new int[g.VerticesCount]; steps[s] = 1; pi[s].Dist = double.PositiveInfinity; bool VisitEdge(Edge e) { if (steps[e.From] == steps[t]) { return(false); } if (steps[e.To] == 0) { steps[e.To] = steps[e.From] + 1; } else if (steps[e.To] != steps[e.From] + 1) { return(true); } var d = Math.Min(pi[e.From].Dist, e.Weight); if (!(pi[e.To].Dist < d)) { return(true); } pi[e.To].Dist = d; pi[e.To].Last = e; return(true); } g.GeneralSearchFrom <EdgesQueue>(s, null, null, VisitEdge); return(pi[t].Dist, g.BuildGraph(s, t, pi)); }