結果
| 問題 |
No.519 アイドルユニット
|
| コンテスト | |
| ユーザー |
tktk_snsn
|
| 提出日時 | 2021-01-12 18:02:30 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,693 bytes |
| コンパイル時間 | 175 ms |
| コンパイル使用メモリ | 82,424 KB |
| 実行使用メモリ | 77,068 KB |
| 最終ジャッジ日時 | 2024-11-21 09:54:19 |
| 合計ジャッジ時間 | 3,841 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 27 WA * 7 |
ソースコード
import heapq
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 7)
inf = 10**6
class MCF_graph(object):
def __init__(self, n):
"""n頂点0辺のグラフを作る"""
self.n = n
self.g = [[] for _ in range(n)] # to, rev, cap, cost
self.pos = []
def add_edge(self, frm, to, cap, cost):
"""frmからtoへ最大容量cap, コストcostの辺を張る. 何番目の辺かを返す"""
m = len(self.pos)
self.pos.append((frm, len(self.g[frm])))
self.g[frm].append([to, len(self.g[to]), cap, cost])
self.g[to].append([frm, len(self.g[frm]) - 1, 0, -cost])
return m
def __get_edge(self, i):
e_to, e_rev, e_cap, e_cost = self.g[self.pos[i][0]][self.pos[i][1]]
re_to, _, re_cap, _ = self.g[e_to][e_rev]
# from, to, cap, flow, cost
return (re_to, e_to, e_cap + re_cap, re_cap, e_cost)
def edges(self):
m = len(self.pos)
for i in range(m):
yield self.__get_edge(i)
def flow(self, s, t, flow_limit=10 ** 18):
""" sからtへflow_limitまで流せるだけ流す。その時の流量とコストを返す """
return self.slope(s, t, flow_limit)[-1]
def slope(self, s, t, flow_limit=10 ** 18):
"""
流量とコストの関係の折れ線を返す.
(0,0)->(flow_0, min_cost_0)->(flow_1, min_cost_1)->...
"""
dual = [0] * self.n
flow = 0
cost = 0
prev_cost = -1
result = [(0, 0)] # cap, cost
while flow < flow_limit:
# call dual_ref()
dist = [10**18] * self.n
pv = [-1] * self.n
pe = [-1] * self.n
vis = [False] * self.n
dist[s] = 0
que = [(0, s)]
while que:
_, v = heapq.heappop(que)
if vis[v]:
continue
vis[v] = True
if v == t:
break
for i, (e_to, _, e_cap, e_cost) in enumerate(self.g[v]):
if vis[e_to] or (not e_cap):
continue
tmp_cost = e_cost - dual[e_to] + dual[v]
if dist[e_to] > dist[v] + tmp_cost:
dist[e_to] = dist[v] + tmp_cost
pv[e_to] = v
pe[e_to] = i
heapq.heappush(que, (dist[e_to], e_to))
if not vis[t]:
break
for v, visited in enumerate(vis):
if not visited:
continue
dual[v] -= dist[t] - dist[v]
# end dual_ref()
c = flow_limit - flow
v = t
while v != s:
c = min(c, self.g[pv[v]][pe[v]][2])
v = pv[v]
v = t
while v != s:
i, j = pv[v], pe[v]
self.g[i][j][2] -= c
self.g[v][self.g[i][j][1]][2] += c
v = i
d = -dual[s]
flow += c
cost += c * d
if prev_cost == d:
result.pop()
result.append((flow, cost))
prev_cost = cost
return result
N = int(input())
F = tuple(tuple(map(int, input().split())) for _ in range(N))
G = MCF_graph(2 * N + 2)
source = 2 * N
sink = source + 1
for i in range(N):
G.add_edge(source, i, 1, 0)
G.add_edge(N + i, sink, 1, 0)
for i in range(N):
for j in range(N):
if i == j:
continue
G.add_edge(i, N + j, inf, inf - F[i][j])
_, cost = G.flow(source, sink, N)
print((N * inf - cost) // 2)
tktk_snsn