Skip to content

Commit

Permalink
mincostflow追加 実装途中 エラー出ます
Browse files Browse the repository at this point in the history
  • Loading branch information
mban259 committed May 13, 2024
1 parent 38c2b36 commit adcfa5c
Showing 1 changed file with 138 additions and 0 deletions.
138 changes: 138 additions & 0 deletions src/main/kotlin/graph/MinCostFlow.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package graph

typealias Capacity = Long
typealias Cost = Long

/**
* Minimum-cost flow problemを扱うライブラリです。
*
* [AC Library](https://atcoder.github.io/ac-library/production/document_ja/mincostflow.html)
*/
class MinCostFlow(private val n: Int) {
private val _edges = mutableListOf<Edge>()

/**
* [from]から[to]へ最大容量[cap], コスト[cost]の辺を追加する。何番目に追加された辺かを返す。
*
* 0 <= [from], [to] < n
*
* 0 <= [cap], [cost]
*/
public fun addEdge(from: Int, to: Int, cap: Capacity, cost: Cost): Int {
assert(from in 0..<n)
assert(to in 0..<n)
assert(0 <= cap)
assert(0 <= cost)
val m = _edges.size
_edges.add(Edge(from, to, cap, 0, cost))
return m
}

/**
* [s]から[t]へ流せるだけ流し、その流量とコストを返す。
* @return (流量,コスト)のPair
*/
public fun flow(s: Int, t: Int): Pair<Capacity, Cost> = flow(s, t, Capacity.MAX_VALUE)

/**
* [s]から[t]へ流量[flowLimit]まで流せるだけ流し、その流量とコストを返す。
* @return (流量,コスト)のPair
*/
public fun flow(s: Int, t: Int, flowLimit: Capacity): Pair<Capacity, Cost> = slope(s, t, flowLimit).last()

/**
* 返り値に流量とコストの関係の折れ線が入る。全てのxについて、流量xのときの最小コストをg(x)とすると、(x,g(x))は返り値を折れ線として見たものに含まれる。
* * 返り値の最初の要素は(0,0)
* * 返り値の.first、.secondは共に狭義単調増加
* * 3点が同一線上にあることはない
* * 返り値の最後の要素は最大流量xとして(x,g(x))
*/
public fun slope(s: Int, t: Int): List<Pair<Capacity, Cost>> = slope(s, t, Capacity.MAX_VALUE)

/**
* 返り値に流量とコストの関係の折れ線が入る。全てのxについて、流量xのときの最小コストをg(x)とすると、(x,g(x))は返り値を折れ線として見たものに含まれる。
* * 返り値の最初の要素は(0,0)
* * 返り値の.first、.secondは共に狭義単調増加
* * 3点が同一線上にあることはない
* * 返り値の最後の要素はy = min(x, [flowLimit])として(y,g(y))
*/
public fun slope(s: Int, t: Int, flowLimit: Capacity): List<Pair<Capacity, Cost>> {
assert(s in 0..<n)
assert(t in 0..<n)
assert(s != t)
val m = _edges.size
val edgeIdx = IntArray(m) { 0 }

val degree = IntArray(n) { 0 }
val redgeIdx = IntArray(m) { 0 }
val elist = ArrayList<Pair<Int, InternalEdge>>(2 * m)
for (i in _edges.indices) {
val e = _edges[i]
edgeIdx[i] = degree[e.from]++
redgeIdx[i] = degree[e.to]++
elist.add(e.from to InternalEdge(e.to, -1, e.cap - e.flow, e.cost))
elist.add(e.to to InternalEdge(e.from, -1, e.flow, -e.cost))
}
val g = CSR(n, elist)
for (i in _edges.indices) {
val e = _edges[i]
edgeIdx[i] += g.start[e.from]
edgeIdx[i] += g.start[e.to]
g.elist[edgeIdx[i]].rev = redgeIdx[i]
g.elist[redgeIdx[i]].rev = edgeIdx[i]
}

val result = slope(g, s, t, flowLimit)

for (i in _edges.indices) {
val e = g.elist[edgeIdx[i]]
_edges[i].flow = _edges[i].cap - e.cap
}

return result
}

private fun slope(g: CSR, s: Int, t: Int, flowLimit: Capacity): List<Pair<Capacity, Cost>> {
val dualDist = Array<MutablePairCostCost>(n) { MutablePairCostCost(-1, -1) }
val prevE = IntArray(n) { 0 }
val vis = BooleanArray(n) { false }

data class Q(val key: Cost, val to: Int) {
operator fun compareTo(r: Q) = -key.compareTo(r.key)
}

val queMin = ArrayDeque<Int>()
val que = ArrayDeque<Q>()

fun dualRef() {
for (i in 0..<n) {
dualDist[i].second = Cost.MAX_VALUE




}
}
}

data class Edge(val from: Int, val to: Int, val cap: Capacity, var flow: Capacity, val cost: Cost)
data class InternalEdge(val to: Int, var rev: Int, val cap: Capacity, val cost: Cost)
data class MutablePairCostCost(var first: Cost, var second: Cost)
class CSR(val n: Int, private val edges: List<Pair<Int, InternalEdge>>) {
val start = IntArray(n + 1) { 0 }
val elist = Array(edges.size) { InternalEdge(-1, -1, -1, -1) }

init {
for (e in edges) {
start[e.first + 1]++
}
for (i in 1..n) {
start[i] += start[i - 1]
}
val counter = start.clone()
for (e in edges) {
elist[counter[e.first]++] = e.second
}
}
}
}

0 comments on commit adcfa5c

Please sign in to comment.