@cedoor/nfa
Version:
TypeScript implementation of some network flow algorithms.
49 lines (39 loc) • 1.9 kB
text/typescript
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]
}