結果
| 問題 |
No.2642 Don't cut line!
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-12-15 01:28:24 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,529 bytes |
| コンパイル時間 | 447 ms |
| コンパイル使用メモリ | 82,432 KB |
| 実行使用メモリ | 149,840 KB |
| 最終ジャッジ日時 | 2024-12-15 01:28:45 |
| 合計ジャッジ時間 | 19,067 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | WA * 3 |
| other | WA * 33 |
ソースコード
## https://yukicoder.me/problems/no/1308
from collections import deque
class UnionFind:
"""
UnionFindの基本的な処理を実装したクラス
"""
def __init__(self, size):
self.root = [i for i in range(size)]
self.size = [1] * size
def get_root(self, v):
if v == self.root[v]:
return v
else:
old_root = self.root[v]
new_root = self.get_root(old_root)
self.root[v] = new_root
return new_root
def merge(self, u, v):
root_u = self.get_root(u)
root_v = self.get_root(v)
if root_u == root_v:
return False
if self.size[root_u] >= self.size[root_v]:
self.size[root_u] += self.size[root_v]
self.root[root_v] = root_u
self.root[v] = root_u
else:
self.size[root_v] += self.size[root_u]
self.root[root_u] = root_v
self.root[u] = root_v
return True
def main():
N, K, C = map(int, input().split())
edges = []
for _ in range(K):
u, v, w, p = map(int, input().split())
edges.append((u - 1, v - 1, w, p))
if N == 1:
print(0)
return
# 最小全域木を計算
edges.sort(key=lambda x : x[2])
uf = UnionFind(N)
used = [False] * K
answer = 0
mst_weight = 0
for i in range(K):
u, v, w, p = edges[i]
if uf.merge(u, v):
mst_weight += w
answer = max(answer, p)
used[i] = True
print(mst_weight, C)
if mst_weight > C:
print(-1)
return
# オイラーツアー計算
next_nodes = [[] for _ in range(N)]
for i in range(K):
if used[i]:
u, v, w, p = edges[i]
next_nodes[u].append((v, w, p))
next_nodes[v].append((u, w, p))
parents = [-2] * N
parents_weigths = [-2] * N
parents[0] = -1
depths = [0] * N
stack = deque()
stack.append((0, 0))
while len(stack) > 0:
v, index = stack.pop()
while index < len(next_nodes[v]):
next_v = next_nodes[v][index][0]
w = next_nodes[v][index][1]
if parents[v] == next_v:
index += 1
continue
parents[next_v] = v
parents_weigths[next_v] = w
depths[next_v] = depths[v] + 1
stack.append((v, index + 1))
stack.append((next_v, 0))
break
max_depth = max(depths)
k = 0
while (1 << k) < max_depth:
k += 1
max_k = k + 1
parents_list = [[-1] * N for _ in range(max_k)]
parents_weights_list = [[-1] * N for _ in range(max_k)]
parents_list[0] = parents
parents_weights_list[0] = parents_weigths
for k in range(1, max_k):
for i in range(N):
p = parents_list[k - 1][i]
w = parents_weights_list[k - 1][i]
if p != -1:
parents_list[k][i] = parents_list[k - 1][p]
parents_weights_list[k][i] = max(parents_weights_list[k - 1][p], w)
# 価値が高い順に
for i in range(K):
if used[i]:
continue
u, v, w_base, p = edges[i]
w0 = -1
if p > answer:
if depths[v] < depths[u]:
u, v = v, u
if depths[u] < depths[v]:
d = depths[v] - depths[u]
for k in reversed(range(max_k)):
if d >= (1 << k):
w0 = max(w0, parents_weights_list[k][v])
v = parents_list[k][v]
d -= 1 << k
if u == v:
if mst_weight - w0 + w_base <= C:
answer = p
continue
for k in reversed(range(max_k)):
if parents_list[k][u] == -1 or parents_list[k][v] == -1:
continue
if parents_list[k][u] != parents_list[k][v]:
w0 = max(w0, parents_weights_list[k][u])
w0 = max(w0, parents_weights_list[k][v])
u = parents_list[k][u]
v = parents_list[k][v]
w0 = max(parents_weigths[u], w0)
w0 = max(parents_weigths[v], w0)
if mst_weight - w0 + w_base <= C:
answer = p
continue
print(answer)
if __name__ == "__main__":
main()