結果
| 問題 |
No.1301 Strange Graph Shortest Path
|
| コンテスト | |
| ユーザー |
wolgnik
|
| 提出日時 | 2020-11-27 23:00:54 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,424 bytes |
| コンパイル時間 | 182 ms |
| コンパイル使用メモリ | 82,396 KB |
| 実行使用メモリ | 309,320 KB |
| 最終ジャッジ日時 | 2024-07-26 20:18:40 |
| 合計ジャッジ時間 | 65,129 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 32 WA * 1 |
ソースコード
import sys
input = sys.stdin.readline
N, M = map(int, input().split())
from heapq import heappop, heappush, heapify
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
mcf = MinCostFlow(N)
edges = []
for _ in range(M):
u, v, c, d = map(int, input().split())
edges.append((u, v, c, d))
mcf.add_edge(u - 1, v - 1, 1, c)
mcf.add_edge(v - 1, u - 1, 1, c)
mcf2 = mcf.flow_with_limit(0, N - 1, 2)
mcf = MinCostFlow(N)
for u, v, c, d in edges:
mcf.add_edge(u - 1, v - 1, 1, c)
mcf.add_edge(v - 1, u - 1, 1, c)
mcf1 = mcf.flow_with_limit(0, N - 1, 1)
if mcf2[0] == 2 and mcf1[1] * 2 == mcf2[1]:
print(mcf2[1])
exit(0)
mcfedges = list(mcf.edges())
mcf = MinCostFlow(N)
for i in range(M):
x = i * 2
fr, to, cap, flow, cost = mcfedges[x]
flow += mcfedges[x + 1][3]
if flow:
mcf.add_edge(fr, to, cap, edges[i][-1])
mcf.add_edge(to, fr, cap, edges[i][-1])
else:
mcf.add_edge(fr, to, cap, cost)
mcf.add_edge(to, fr, cap, cost)
res = mcf1[1] + mcf.flow_with_limit(0, N - 1, 1)[1]
if mcf2[0] == 2: res = min(res, mcf2[1])
print(res)
wolgnik