結果
| 問題 |
No.1301 Strange Graph Shortest Path
|
| コンテスト | |
| ユーザー |
Kite_kuma
|
| 提出日時 | 2020-10-30 22:26:41 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 1,743 ms / 3,000 ms |
| コード長 | 4,353 bytes |
| コンパイル時間 | 440 ms |
| コンパイル使用メモリ | 82,288 KB |
| 実行使用メモリ | 279,592 KB |
| 最終ジャッジ日時 | 2024-09-13 00:27:03 |
| 合計ジャッジ時間 | 45,984 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 33 |
ソースコード
from heapq import heappop, heappush, heapify
import sys
input = sys.stdin.readline
# N, K = map(int, input().split())
# a = [list(map(int, input().split())) for _ in range(N)]
class MinCostFlow():
def __init__(self, n):
self.n = n
self.graph = [[] for _ in range(n)]
self.pos = []
def add_edge(self, fr, to, cap, cost):
m = len(self.pos)
self.pos.append((fr, len(self.graph[fr])))
self.graph[fr].append([to, len(self.graph[to]), cap, cost])
self.graph[to].append([fr, len(self.graph[fr]) - 1, 0, -cost])
return m
def get_edge(self, idx):
to, rev, cap, cost = self.graph[self.pos[idx][0]][self.pos[idx][1]]
rev_to, rev_rev, rev_cap, rev_cost = self.graph[to][rev]
return self.pos[idx][0], to, cap + rev_cap, rev_cap, cost
def edges(self):
for i in range(len(self.pos)):
yield self.get_edge(i)
def dual_ref(self, s, t):
dist = [2**63 - 1] * self.n
dist[s] = 0
vis = [0] * self.n
self.pv = [-1] * self.n
self.pe = [-1] * self.n
queue = []
heappush(queue, (0, s))
while queue:
k, v = heappop(queue)
if vis[v]:
continue
vis[v] = True
if v == t:
break
for i in range(len(self.graph[v])):
to, rev, cap, cost = self.graph[v][i]
if vis[to] or cap == 0:
continue
cost += self.dual[v] - self.dual[to]
if dist[to] - dist[v] > cost:
dist[to] = dist[v] + cost
self.pv[to] = v
self.pe[to] = i
heappush(queue, (dist[to], to))
if not vis[t]:
return False
for v in range(self.n):
if not vis[v]:
continue
self.dual[v] -= dist[t] - dist[v]
return True
def flow(self, s, t): return self.flow_with_limit(s, t, 2**63 - 1)
def flow_with_limit(
self, s, t, limit): return self.slope_with_limit(s, t, limit)[-1]
def slope(self, s, t): return self.slope_with_limit(s, t, 2**63 - 1)
def slope_with_limit(self, s, t, limit):
flow = 0
cost = 0
prev_cost = -1
res = [(flow, cost)]
self.dual = [0] * self.n
while flow < limit:
if not self.dual_ref(s, t):
break
c = limit - flow
v = t
while v != s:
c = min(c, self.graph[self.pv[v]][self.pe[v]][2])
v = self.pv[v]
v = t
while v != s:
to, rev, cap, _ = self.graph[self.pv[v]][self.pe[v]]
self.graph[self.pv[v]][self.pe[v]][2] -= c
self.graph[v][rev][2] += c
v = self.pv[v]
d = -self.dual[s]
flow += c
cost += c * d
if prev_cost == d:
res.pop()
res.append((flow, cost))
prev_cost = cost
return res
inf = 10 ** 10
# mcf = MinCostFlow(2 * N + 2)
# mcf.add_edge(2 * N, 2 * N + 1, N * K, inf)
# for i in range(N):
# mcf.add_edge(2 * N, i, K, 0)
# mcf.add_edge(N + i, 2 * N + 1, K, 0)
# for j in range(N):
# mcf.add_edge(i, N + j, 1, inf - a[i][j])
# print(-mcf.flow_with_limit(2 * N, 2 * N + 1, N * K)[1] + N * K * inf)
# res = [["."] * N for _ in range(N)]
# for f, t, _, flow, _ in mcf.edges():
# if flow == 0 or max(f, t) >= 2 * N:
# continue
# res[f][t - N] = "X"
# for r in res:
# print("".join(r))
def main() -> None:
n, m = map(int, input().split())
s, t = 0, n - 1
# graph = mcf_graph(n + m)
graph = MinCostFlow(n + m)
for i in range(m):
u, v, c, d = map(int, input().split())
assert 1 <= u <= n and 1 <= v <= n and c <= d
u -= 1
v -= 1
mid = n + i
graph.add_edge(u, mid, 2, c)
graph.add_edge(mid, v, 1, 0)
graph.add_edge(mid, v, 1, d - c)
graph.add_edge(v, mid, 2, c)
graph.add_edge(mid, u, 1, 0)
graph.add_edge(mid, u, 1, d - c)
# flow, cost = graph.flow(s, t, 2)
flow, cost = graph.flow_with_limit(s, t, 2)
assert flow == 2
print(cost)
if __name__ == '__main__':
main()
Kite_kuma