結果
問題 | No.2642 Don't cut line! |
ユーザー |
![]() |
提出日時 | 2024-02-17 19:47:41 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 2,229 ms / 4,000 ms |
コード長 | 4,467 bytes |
コンパイル時間 | 306 ms |
コンパイル使用メモリ | 82,548 KB |
実行使用メモリ | 209,980 KB |
最終ジャッジ日時 | 2024-09-29 03:31:19 |
合計ジャッジ時間 | 44,310 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 33 |
ソースコード
import mathfrom collections import namedtupleINF = 10**16class UnionFind:def __init__(self, N):self.par = list(range(N))self.size = [1] * Ndef root(self, x):if self.par[x] == x:return xelse:self.par[x] = self.root(self.par[x])return self.par[x]def issame(self, x, y):return self.root(x) == self.root(y)def unite(self, x, y):x = self.root(x)y = self.root(y)if x == y:return Trueif self.size[x] < self.size[y]:self.par[x] = yself.size[y] += self.size[x]else:self.par[y] = xself.size[x] += self.size[y]return TrueEdge = namedtuple('Edge', ['from_', 'to', 'weight', 'profit'])def reverse(edge):return Edge(edge.to, edge.from_, edge.weight, edge.profit)class Graph:def __init__(self, N):self.edges = [[] for _ in range(N)]def all_edges(self):return [edge for edge_list in self.edges for edge in edge_list]def add(self, edge, has_dir=False):self.edges[edge.from_].append(edge)if not has_dir:self.edges[edge.to].append(reverse(edge))def as_rooted_tree(graph, root):N = len(graph.edges)tree = Graph(N)stack = [(root, -1)]while stack:v, p = stack.pop()for u in graph.edges[v]:if u.to != p:tree.add(u, has_dir=True)stack.append((u.to, v))return treedef kruskal(sorted_edges, N):uf = UnionFind(N)graph = Graph(N)cost = 0profit = -1for edge in sorted_edges:if not uf.issame(edge.from_, edge.to):uf.unite(edge.from_, edge.to)graph.add(edge)cost += edge.weightprofit = max(profit, edge.profit)return graph, cost, profitclass LCA:def __init__(self, graph, root=0):V = len(graph.edges)K = math.ceil(math.log2(V))tree = as_rooted_tree(graph, root)self.parent = [[-1] * V for _ in range(K)]self.dist = [[-1] * V for _ in range(K)]self.depth = [-1] * Vself.K = Kself.V = Vstack = [(root, -1, 0)]while stack:v, p, d = stack.pop()self.depth[v] = dself.parent[0][v] = pfor u in tree.edges[v]:if u.to != p:self.dist[0][u.to] = u.weightstack.append((u.to, v, d + 1))for k in range(K - 1):for v in range(V):if self.parent[k][v] != -1:self.parent[k + 1][v] = self.parent[k][self.parent[k][v]]self.dist[k + 1][v] = max(self.dist[k][v], self.dist[k][self.parent[k][v]])def max_cost(self, u, v):cost = -INFif self.depth[u] < self.depth[v]:u, v = v, udiff = self.depth[u] - self.depth[v]for k in range(self.K):if (diff >> k) & 1:cost = max(cost, self.dist[k][u])u = self.parent[k][u]if u == v:return costfor k in range(self.K - 1, -1, -1):if self.parent[k][u] != self.parent[k][v]:cost = max(cost, self.dist[k][u])cost = max(cost, self.dist[k][v])u = self.parent[k][u]v = self.parent[k][v]cost = max(cost, self.dist[0][u])cost = max(cost, self.dist[0][v])return costdef main():N, K, C = map(int, input().split())graph = Graph(N)for _ in range(K):u, v, w, p = map(int, input().split())u -= 1v -= 1edge = Edge(u, v, w, p)graph.add(edge)sorted_edges = graph.all_edges()sorted_edges.sort(key=lambda x: x.weight)mst, C_m, P_m = kruskal(sorted_edges, N)mst_edges_set = set(mst.all_edges())mst_tree = as_rooted_tree(mst, 0)lca = LCA(mst_tree)sorted_edges.sort(key=lambda x: x.profit, reverse=True)for edge in sorted_edges:P = edge.profitif edge in mst_edges_set:C_add = 0C_rem = 0else:u, v = edge.from_, edge.toC_add = edge.weightC_rem = lca.max_cost(u, v)if C_m + C_add - C_rem <= C:print(P)returnprint(-1)if __name__ == "__main__":main()