UNPKG

@cedoor/nfa

Version:

TypeScript implementation of some network flow algorithms.

49 lines (39 loc) 1.9 kB
import Graph, { GraphData } from "../dataStructures/graph" import edmondsKarp from "../maximumFlowAlgorithms/edmondsKarp" import bellmanFord from "../shortestPathAlgorithms/bellmanFord" import { getResidualCapacity, sendFlow, getResidualGraph, getOptimalGraph } from "../utils" /** * The Cycle-Canceling algorithm solves the minimum-cost flow problem * starting from a feasible graph obtained with a maximum flow algorithm * and, as long as negative cost cycles exist, augment the flow along * this cycles. This implementation uses the Edmonds-Karp algorithm to * solve the maximum flow problem in O(n * m^2), and the Bellman-Fort * algorithm to find the negative cycles in O(m * n). * Time complexity: O (n * m^2 * C * U). * @param {Graph | GraphData} The graph to visit. * @returns {[Graph, number, number]} The optimal graph, the maximum flow and the minimum cost. */ export default function cycleCanceling(graph: Graph | GraphData): [Graph, number, number] { if (!(graph instanceof Graph)) { graph = new Graph(graph) } const [optimalGraph, maximumFlow, , sinkNodeId] = edmondsKarp(graph) const residualGraph = getResidualGraph(optimalGraph) let negativeCycle = bellmanFord(residualGraph, sinkNodeId) while (negativeCycle && Array.isArray(negativeCycle)) { negativeCycle.push(negativeCycle[0]) const residualCapacity = getResidualCapacity(residualGraph, negativeCycle) sendFlow(residualGraph, negativeCycle, residualCapacity) negativeCycle = bellmanFord(residualGraph, sinkNodeId) } // Calculates the minimum cost. let minimumCost = 0 for (const node of residualGraph.getNodes()) { for (const arc of node.getArcs()) { if (arc.cost < 0) { minimumCost -= arc.cost } } } return [getOptimalGraph(residualGraph), maximumFlow, minimumCost] }