結果
| 問題 |
No.1812 Uribo Road
|
| コンテスト | |
| ユーザー |
MasKoaTS
|
| 提出日時 | 2022-01-12 22:06:17 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 1,340 ms / 5,000 ms |
| コード長 | 3,295 bytes |
| コンパイル時間 | 257 ms |
| コンパイル使用メモリ | 82,176 KB |
| 実行使用メモリ | 119,908 KB |
| 最終ジャッジ日時 | 2024-11-15 14:26:30 |
| 合計ジャッジ時間 | 16,355 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 30 |
ソースコード
import heapq as hq
import sys
input = sys.stdin.readline
INF = 10 ** 18
"""
Union-Find
from : https://github.com/customaddone/beginPython/blob/master/cgi-bin/library/unionfind/unionfind.py
ref : https://algo-logic.info/union-find-tree/
"""
class UnionFind():
#Uni = UnionFind(n) のようにする
def __init__(self, n):
self.n = n
self.parents = [-1] * n
#xの親(親がいないときは自身の番号を返す)
def find(self, x):
if self.parents[x] < 0:
return x
else:
self.parents[x] = self.find(self.parents[x])
return self.parents[x]
#xとyを関係付ける
def union(self, x, y):
x = self.find(x)
y = self.find(y)
if x == y:
return
if self.parents[x] > self.parents[y]:
x, y = y, x
# if x > y: # よりrootのインデックスが小さい方が親
# x, y = y, x
self.parents[x] += self.parents[y]
self.parents[y] = x
#xとyが同じ組に属するかどうか
def same(self, x, y):
return self.find(x) == self.find(y)
#xが属する組の大きさ
def size(self, x):
return -self.parents[self.find(x)]
#xが属する組の全要素をリストとして取得
def members(self, x):
root = self.find(x)
return [i for i in range(self.n) if self.find(i) == root]
#Union-Find木の根に当たる要素全てをリストとして取得
def roots(self):
return [i for i, x in enumerate(self.parents) if x < 0]
#Union-Find木の根とそれに属する組の全要素
def all_group_members(self):
return {r: self.members(r) for r in self.roots()}
N,M,K = map(int, input().split())
if not(2 <= N <= 10 ** 4 and N - 1 <= M <= min(2 * 10 ** 4, N * (N - 1) // 2) and 1 <= K <= min(12, M)):
exit(1)
R = [i - 1 for i in map(int, input().split())]
S = set(R)
if any(not(1 <= i + 1 <= M) for i in S):
exit(1)
if not(len(S) == len(R) == K):
exit(1)
edge = [[] for _ in [0] * M]
route = [[] for _ in [0] * N]
abst = set([])
uni = UnionFind(N)
for i in range(M):
a,b,c = map(int, input().split())
if((a,b) in abst):
exit(1)
abst.add((a,b)); abst.add((b,a))
if not(1 <= a <= N and 1 <= b <= N and a != b and 1 <= c <= 10 ** 4):
exit(1)
a -= 1; b -= 1
uni.union(a,b)
route[a].append((b,c))
route[b].append((a,c))
if(i in S):
edge[i] = [a,b,c]
if not(uni.size(0) == N):
exit(1)
def dijkstra(s,route):
que = [(0,s)]
dist = [INF] * N
while(que):
d,v = hq.heappop(que)
if(dist[v] < INF):
continue
dist[v] = d
for nv,nd in route[v]:
hq.heappush(que,(d + nd, nv))
return dist
dist = [[] for _ in [0] * N]
T = set([0,N - 1])
for i in S:
T.add(edge[i][0])
T.add(edge[i][1])
for i in T:
dist[i] = dijkstra(i,route)
dp = [[[INF] * 2 for _ in [0] * K] for _ in [0] * (1 << K)]
for i in range(K):
for j in range(2):
dp[1 << i][i][j] = dist[0][edge[R[i]][j ^ 1]] + edge[R[i]][2]
for bit in range(1, 1 << K):
for s in range(K):
if not(bit & (1 << s)):
continue
for t in range(K):
if(bit & (1 << t)):
continue
b = bit | (1 << t); c = edge[R[t]][2]
for x in range(2):
for y in range(2):
p = edge[R[s]][x]; q = edge[R[t]][y ^ 1]
d = dp[bit][s][x] + dist[p][q] + c
if(dp[b][t][y] > d):
dp[b][t][y] = d
ans = INF
for i in range(K):
for j in range(2):
d = dp[-1][i][j] + dist[edge[R[i]][j]][N - 1]
if(ans > d):
ans = d
print(ans)
MasKoaTS