結果
問題 | No.2604 Initial Motion |
ユーザー |
![]() |
提出日時 | 2024-01-12 22:30:10 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 851 ms / 3,000 ms |
コード長 | 6,488 bytes |
コンパイル時間 | 271 ms |
コンパイル使用メモリ | 82,540 KB |
実行使用メモリ | 82,980 KB |
最終ジャッジ日時 | 2024-09-27 23:05:23 |
合計ジャッジ時間 | 15,876 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 39 |
ソースコード
# https://atcoder.jp/contests/practice2/submissions/33588016import heapqfrom heapq import heappush, heappopclass MinCostFlow:"""https://github.com/atcoder/ac-library/blob/master/atcoder/internal_csr.hpphttps://github.com/atcoder/ac-library/blob/master/atcoder/mincostflow.hpphttps://github.com/atcoder/ac-library/blob/master/document_en/mincostflow.mdhttps://github.com/atcoder/ac-library/blob/master/document_ja/mincostflow.md"""def __init__(self, n):self.n = nself._edges = []def add_edge(self, fr, to, cap, cost):assert 0 <= fr < self.nassert 0 <= to < self.nassert 0 <= capassert 0 <= costself._edges.append(self.edge(fr, to, cap, cost))return len(self._edges) - 1class edge:def __init__(self, fr, to, cap, cost):self.fr = frself.to = toself.cap = capself.flow = 0self.cost = costdef get_edge(self, i):assert 0 <= i < len(self._edges)return self._edges[i]def edges(self):return self._edgesdef flow(self, s, t, flow_limit=1<<60):return self.slope(s, t, flow_limit)[-1]def __csr(self, edges):# Compressed Sparse Rowself.start = [0] * (self.n + 1)for fr, _ in edges:self.start[fr + 1] += 1for i in range(self.n):self.start[i + 1] += self.start[i]counter = self.start.copy()self.elist = [0] * len(edges)for fr, e in edges:self.elist[counter[fr]] = ecounter[fr] += 1class _edge:def __init__(self, to, rev, cap, cost):self.to = toself.rev = revself.cap = capself.cost = costdef __g(self):degree = [0] * self.nredge_idx = [0] * self.melist = [(0, None)] * (2 * self.m)now_elist = 0for i in range(self.m):e = self._edges[i]self.edge_idx[i] = degree[e.fr]degree[e.fr] += 1redge_idx[i] = degree[e.to]degree[e.to] += 1elist[now_elist] = (e.fr, self._edge(e.to, -1, e.cap - e.flow, e.cost))now_elist += 1elist[now_elist] = (e.to, self._edge(e.fr, -1, e.flow, -e.cost))now_elist += 1self.__csr(elist)for i in range(self.m):e = self._edges[i]self.edge_idx[i] += self.start[e.fr]redge_idx[i] += self.start[e.to]self.elist[self.edge_idx[i]].rev = redge_idx[i]self.elist[redge_idx[i]].rev = self.edge_idx[i]def slope(self, s, t, flow_limit=1<<60):assert 0 <= s < self.nassert 0 <= t < self.nassert s != tself.m = len(self._edges)self.edge_idx = [0] * self.mself.__g()result = self.__slope(s, t, flow_limit)for i in range(self.m):e = self.elist[self.edge_idx[i]]self._edges[i].flow = self._edges[i].cap - e.capreturn resultdef __dual_ref(self, s, t):log = self.n.bit_length()mask = (1<<log) - 1dist = [1<<60] * self.nvis = [0] * self.nque_min = []que = []dist[s] = 0que_min.append(s)while que_min or que:if que_min:v = que_min.pop()else:v = heappop(que) & maskif vis[v]:continuevis[v] = 1if v == t:break# dist[v] = shortest(s, v) + dual[s] - dual[v]# dist[v] >= 0 (all reduced cost are positive)# dist[v] <= (n-1)Cdual_v = self.dual[v]dist_v = dist[v]for i in range(self.start[v], self.start[v+1]):e = self.elist[i]if not e.cap:continue# |-dual[e.to] + dual[v]| <= (n-1)C# cost <= C - -(n-1)C + 0 = nCcost = e.cost - self.dual[e.to] + dual_vif dist[e.to] - dist_v > cost:dist_to = dist_v + costdist[e.to] = dist_toself.prev_e[e.to] = e.revif dist_to == dist_v:que_min.append(e.to)else:heappush(que, dist_to<<log | e.to)if not vis[t]:return Falsefor v in range(self.n):if not vis[v]:continue# dual[v]# = dual[v] - dist[t] + dist[v]# = dual[v] - (shortest(s, t) + dual[s] - dual[t]) + (shortest(s, v) + dual[s] - dual[v])# = - shortest(s, t) + dual[t] + shortest(s, v)# = shortest(s, v) - shortest(s, t)# >= 0 - (n-1)Cself.dual[v] -= dist[t] - dist[v]return Truedef __slope(self, s, t, flow_limit):# variants (C = maxcost):# -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0# reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edgeself.dual = [0] * self.nself.prev_e = [0] * self.nflow = 0cost = 0prev_cost_per_flow = -1result = [(0, 0)]while flow < flow_limit:if not self.__dual_ref(s, t):breakc = flow_limit - flowv = twhile v != s:c = min(c, self.elist[self.elist[self.prev_e[v]].rev].cap)v = self.elist[self.prev_e[v]].tov = twhile v != s:e = self.elist[self.prev_e[v]]e.cap += cself.elist[e.rev].cap -= cv = self.elist[self.prev_e[v]].tod = -self.dual[s]flow += ccost += c * dif prev_cost_per_flow == d:result.pop()result.append((flow, cost))prev_cost_per_flow = dreturn resultfrom collections import Counterk,n,m = map(int,input().split())a = Counter(map(int,input().split()))b = list(map(int,input().split()))g = MinCostFlow(n+2)for i,v in a.items(): g.add_edge(0,i,v,0)for i,v in enumerate(b,1): g.add_edge(i,n+1,v,0)for _ in range(m):u,v,d = map(int,input().split())g.add_edge(u,v,k,d); g.add_edge(v,u,k,d)print(g.flow(0,n+1)[1])