結果
問題 | No.2604 Initial Motion |
ユーザー |
|
提出日時 | 2024-01-13 01:02:11 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 873 ms / 3,000 ms |
コード長 | 8,392 bytes |
コンパイル時間 | 275 ms |
コンパイル使用メモリ | 82,304 KB |
実行使用メモリ | 83,568 KB |
最終ジャッジ日時 | 2024-09-28 00:55:13 |
合計ジャッジ時間 | 17,657 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 39 |
ソースコード
# https://yukicoder.me/submissions/943504# https://atcoder.jp/contests/practice2/submissions/20654283import heapqclass mcf_graph_int_cost:"""It solves Minimum-cost flow problem."""def __init__(self, n):"""It creates a directed graph with n vertices and 0 edges.Cap and Cost are the type of the capacity and the cost, respectively.Constraints-----------> 0 <= n <= 10 ** 8> Cap and Cost are int.Complexity----------> O(n)"""self.n = nself._edges = []def add_edge(self, from_, to, cap, cost):"""It adds an edge oriented from `from_` to `to` with capacity `cap` and cost `cost`.It returns an integer k such that this is the k-th edge that is added.Constraints-----------> 0 <= from_, to < n> 0 <= cap, costComplexity----------> O(1) amortized"""# assert 0 <= from_ < self.n# assert 0 <= to < self.n# assert 0 <= cap# assert 0 <= costm = len(self._edges)self._edges.append(self.__class__.edge(from_, to, cap, 0, cost))return mclass edge:def __init__(self, from_, to, cap, flow, cost):self.from_ = from_self.to = toself.cap = capself.flow = flowself.cost = costdef get_edge(self, i):"""It returns the current internal state of the edges.The edges are ordered in the same order as added by add_edge.Constraints-----------> 0 <= i < mComplexity----------> O(1)"""# assert 0 <= i < len(self._edges)return self._edges[i]def edges(self):"""It returns the current internal state of the edges.The edges are ordered in the same order as added by add_edge.Complexity----------> O(m), where m is the number of added edges."""return self._edges.copy()def _dual_ref(self, s, t):self.dist = [4611686018427387903] * self.nself.vis = [False] * self.nself.que_min.clear()self.que.clear()que_push_que = []self.dist[s] = 0self.que_min.append(s)while self.que_min or self.que or que_push_que:if self.que_min:v = self.que_min.pop()else:while que_push_que:heapq.heappush(self.que, que_push_que.pop())v = heapq.heappop(self.que) & 9223372036854775807if self.vis[v]:continueself.vis[v] = Trueif v == t:breakdual_v = self.dual[v]dist_v = self.dist[v]for i in range(self.start[v], self.start[v + 1]):e = self.elist[i]if not e.cap:continuecost = e.cost - self.dual[e.to] + dual_vif self.dist[e.to] - dist_v > cost:dist_to = dist_v + costself.dist[e.to] = dist_toself.prev_e[e.to] = e.revif dist_to == dist_v:self.que_min.append(e.to)else:que_push_que.append((dist_to << 64) + e.to)if not self.vis[t]:return Falsefor v in range(self.n):if not self.vis[v]:continueself.dual[v] -= self.dist[t] - self.dist[v]return Truedef _csr(self):m = len(self._edges)self.edge_idx = [0] * mredge_idx = [0] * mdegree = [0] * self.nedges = []for i, e in enumerate(self._edges):self.edge_idx[i] = degree[e.from_]degree[e.from_] += 1redge_idx[i] = degree[e.to]degree[e.to] += 1edges.append((e.from_, self.__class__._edge(e.to, -1, e.cap - e.flow, e.cost)))edges.append((e.to, self.__class__._edge(e.from_, -1, e.flow, -e.cost)))self.start = [0] * (self.n + 1)self.elist = [0] * len(edges)for v, w in edges:self.start[v + 1] += 1for i in range(1, self.n + 1):self.start[i] += self.start[i-1]counter = self.start.copy()for v, w in edges:self.elist[counter[v]] = wcounter[v] += 1for i, e in enumerate(self._edges):self.edge_idx[i] += self.start[e.from_]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=4611686018427387903):"""Let g be a function such that g(x) is the cost of the minimum cost s-t flowwhen the amount of the flow is exactly x.g is known to be piecewise linear.It returns g as the list of the changepoints, that satisfies the followings.> The first element of the list is (0, 0).> Both of element[0] and element[1] are strictly increasing.> No three changepoints are on the same line.> (1) The last element of the list is (x, g(x)), where x is the maximum amount of the s-t flow.> (2) The last element of the list is (y, g(y)), where y = min(x, flow_limit).Constraints-----------Let x be the maximum cost among all edges.> s != t> You can't call min_cost_slope or min_cost_max_flow multiple times.> 0 <= nx <= 2 * 10 ** 9 + 1000Complexity----------> O(F (n + m) log (n + m)), where F is the amount of the flow and m is the number of added edges."""# assert 0 <= s < self.n# assert 0 <= t < self.n# assert s != tself._csr()self.dual = [0] * self.nself.dist = [4611686018427387903] * self.nself.prev_e = [0] * self.nself.vis = [False] * self.nflow = 0cost = 0prev_cost_per_flow = -1result = [(0, 0)]self.que = []self.que_min = []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 = dfor i in range(len(self._edges)):e = self.elist[self.edge_idx[i]]self._edges[i].flow = self._edges[i].cap - e.capreturn resultdef flow(self, s, t, flow_limit=4611686018427387903):"""It augments the flow from s to t as much as possible.It returns the amount of the flow and the cost.(1) It augments the s-t flow as much as possible.(2) It augments the s-t flow as much as possible, until reaching the amount of flow_limit.Constraints-----------> same as mcf_graph.slopeComplexity----------> same as mcf_graph.slope"""return self.slope(s, t, flow_limit)[-1]class _edge:def __init__(self, to, rev, cap, cost):self.to = toself.rev = revself.cap = capself.cost = costfrom collections import Counterk,n,m = map(int,input().split())a = Counter(map(int,input().split()))b = list(map(int,input().split()))g = mcf_graph_int_cost(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,2*k,d); g.add_edge(v,u,2*k,d)print(g.flow(0,n+1)[1])