Problem:


ゾンビ島 (Zombie Island)

  問題

JOI 君が住んでいる島がゾンビに侵略されてしまった．JOI 君は島で一番安全な避難場所として設定されているシェルターに逃げ込むことにした．

JOI 君が住んでいる島は町 1 から町 N までの N 個の町からなり，町と町とは道路で結ばれている．島には M 本の道路があり，すべての道路は異なる 2 つの町を結んでいる．JOI 君は道路を双方向に自由に移動できるが，道路以外を通って町から別の町に行くことはできない．

いくつかの町はゾンビに支配されており，訪れることが出来ない．ゾンビに支配されている町から S 本以下の道路を使って到達できる町を危険な町という．それ以外の町を危険でない町という．

JOI 君の家は町 1 にあり，避難先のシェルターは町 N にある．町 1，町 N はゾンビに支配されていない．島の道路は移動するのに時間がかかるので，JOI 君は町を移動するたびに，移動先の町で一晩宿泊しなければならない．JOI 君は，危険でない町で宿泊する場合は宿泊費が P 円の安い宿に泊まるが，危険な町で宿泊する場合はセキュリティのサービスが優良な宿泊費が Q 円の高級宿に泊まる．JOI 君はできるだけ宿泊費が安くなるように移動して，町 N まで避難したい．町 1 や町 N では宿泊する必要はない．

JOI 君が 町 1 から町 N まで移動するときに必要な宿泊費の合計の最小値を求めよ．

  入力

入力は 2 + K + M 行からなる．

1 行目には，4 つの整数 N, M, K,  S (2 ≦ N ≦ 100000, 1 ≦ M ≦ 200000, 0 ≦ K ≦ N - 2, 0 ≦ S ≦ 100000) が空白を区切りとして書かれている．これは，島が N 個の町と M 本の道路からなり，N 個の町のうち K 個の町がゾンビに支配されており，ゾンビに支配されている町から S 本以下の道路を使って到達できる町を危険な町と呼ぶことを表す．

2 行目には，2 つの整数 P, Q (1 ≦ P ＜ Q ≦ 100000) が空白を区切りとして書かれている．これは，JOI 君が危険でない町では宿泊費が P 円の宿に泊まり，危険な町では宿泊費が Q 円の宿に泊まることを表す．

続く K 行のうちの i 行目 (1 ≦ i ≦ K) には，整数 Ci (2 ≦ Ci ≦ N - 1) が書かれている．これは，町 Ci がゾンビに支配されていることを表す．C1, ..., CK は全て異なる．

続く M 行のうちの j 行目 (1 ≦ j ≦ M) には，2 つの整数 Aj, Bj (1 ≦ Aj ＜ Bj ≦ N) が空白を区切りとして書かれている．これは，町 Aj と町 Bj との間に道路が存在することを表す．同じ (Aj, Bj) の組が 2 回以上書かれていることはない．

与えられる入力データにおいては，町 1 から町 N までゾンビに支配されていない町のみを通って移動できることが保証されている．

  出力

JOI 君が町 1 から町 N まで移動するときに必要な宿泊費の合計の最小値を 1 行で出力せよ．

出力が 32 ビット符号付き整数の範囲に収まるとは限らないことに注意せよ．

  入出力例

  
入力例 1
  

  

13 21 1 1
1000 6000
7
1 2
3 7
2 4
5 8
8 9
2 5
3 4
4 7
9 10
10 11
5 9
7 12
3 6
4 5
1 3
11 12
6 7
8 11
6 13
7 8
12 13

出力例 1

11000

  
入力例 2
  

  

21 26 2 2
1000 2000
5
16
1 2
1 3
1 10
2 5
3 4
4 6
5 8
6 7
7 9
8 10
9 10
9 11
11 13
12 13
12 15
13 14
13 16
14 17
15 16
15 18
16 17
16 19
17 20
18 19
19 20
19 21

出力例 2

  

15000

入出力例 1 は，以下の図に対応している．円は町を，線は道路を表す．

この場合，町 3，町 4，町 6，町 8，町 12 が危険な町である．

以下のような順番で町を移動すると，宿泊費の合計を最小にできる．

町 1 から町 2 に行く．町 2 で宿泊費が 1000 円の安い宿に宿泊する．

町 2 から町 5 に行く．町 5 で宿泊費が 1000 円の安い宿に宿泊する．

町 5 から町 9 に行く．町 9 で宿泊費が 1000 円の安い宿に宿泊する．

町 9 から町 10 に行く．町 10 で宿泊費が 1000 円の安い宿に宿泊する．

町 10 から町 11 に行く．町 11 で宿泊費が 1000 円の安い宿に宿泊する．

町 11 から町 12 に行く．町 12 で宿泊費が 6000 円の高級宿に宿泊する．

町 12 から町 13 に行く．町 13 では宿泊しない．

JOI 君がこのような経路で移動したとき，宿泊費の合計は 11000 円になるので，11000 を出力する．

情報オリンピック日本委員会作 『第 15 回日本情報オリンピック JOI 2015/2016 予選競技課題』



Sample input:
13 21 1 1
1000 6000
7
1 2
3 7
2 4
5 8
8 9
2 5
3 4
4 7
9 10
10 11
5 9
7 12
3 6
4 5
1 3
11 12
6 7
8 11
6 13
7 8
12 13


Sample output:
11000

Submission status: Accepted

Solution code:
from heapq import heappush, heappop
INF = 10 ** 20

n, m, k, s = map(int, input().split())
p, q = map(int, input().split())
z_dist = [INF] * n
que = []
for _ in range(k):
  c = int(input()) - 1
  z_dist[c] = 0
  heappush(que, (0, c))

edges = [[] for _ in range(n)]
for _ in range(m):
  a, b = map(int, input().split())
  a -= 1
  b -= 1
  edges[a].append(b)
  edges[b].append(a)

while que:
  total, node = heappop(que)
  for to in edges[node]:
    if z_dist[to] > total + 1:
      z_dist[to] = total + 1
      heappush(que, (total + 1, to))

cost = [INF] * n
cost[0] = 0
que = []
heappush(que, (0, 0))
while que:
  total, node = heappop(que)
  for to in edges[node]:
    if to == n - 1:
      if cost[to] > total:
        cost[to] = total
        continue
    if z_dist[to] == 0:
      continue
    if z_dist[to] <= s:
      price = q
    else:
      price = p

    if cost[to] > total + price:
      cost[to] = total + price
      heappush(que, (total + price, to))

print(cost[n - 1])

Submission status: Accepted

Solution code:
from heapq import heappush, heappop
INF = 10 ** 20

n, m, k, s = map(int, input().split())
p, q = map(int, input().split())
z_dist = [INF] * n
que = []
for _ in range(k):
  c = int(input()) - 1
  z_dist[c] = 0
  heappush(que, (0, c))

edges = [[] for _ in range(n)]
for _ in range(m):
  a, b = map(int, input().split())
  a -= 1
  b -= 1
  edges[a].append(b)
  edges[b].append(a)

while que:
  total, node = heappop(que)
  for to in edges[node]:
    if z_dist[to] > total + 1:
      z_dist[to] = total + 1
      heappush(que, (total + 1, to))

cost = [INF] * n
cost[0] = 0
que = []
heappush(que, (0, 0))
while que:
  total, node = heappop(que)
  for to in edges[node]:
    if to == n - 1:
      print(total)
      que = []
      break
    if z_dist[to] == 0:
      continue
    if z_dist[to] <= s:
      price = q
    else:
      price = p

    if cost[to] > total + price:
      cost[to] = total + price
      heappush(que, (total + price, to))

Submission status: Accepted

Solution code:
from collections import deque
from heapq import heappop,heappush
inf=float("INF")
dq=[]

n,m,k,s=map(int,input().split())
p,q=map(int,input().split())

c=[0]*k
z_dist=[inf]*n
for i in range(k):
    c[i]=int(input())-1
    z_dist[c[i]]=0
    heappush(dq,(0,c[i]))
    
g=[[] for i in range(m)]
a=[0]*m
b=[0]*m
for j in range(m):
    aj,bj=map(int,input().split())
    g[aj-1].append(bj-1)    
    g[bj-1].append(aj-1) 
    a[j]=aj-1
    b[j]=bj-1
  
cc=[p]*n    
    
while dq:
    total,node=heappop(dq)
    for to in g[node]:
        if z_dist[to]>total+1:
            z_dist[to]=total+1
            heappush(dq,(total+1,to))

for i in range(n):
    if z_dist[i]<=s:
        cc[i]=q

g=[[] for i in range(n)]
for i in range(m):
    if (not a[i] in c) and (not b[i] in c):
        g[a[i]].append((b[i],cc[b[i]]))
        g[b[i]].append((a[i],cc[a[i]]))

hq=[]
rst=0
heappush(hq,(0,rst)) 

dist=[inf]*n
dist[rst]=0
while len(hq)>0:
    dd,state = heappop(hq)
    for v,dv in g[state]:
        if dist[v]>dist[state]+dv:
            dist[v]=dist[state]+dv
            heappush(hq,(dist[v],v))

print(dist[n-1]-cc[n-1])

Submission status: Accepted

Solution code:
from collections import deque
import heapq

N,M,K,S = map(int,input().split())
# - N nodes, M edges, K zombie nodes
# - S本以下の道路を使って到達できる街 = 危険な街

P,Q = map(int,input().split())
# - P: not dangerous
# - Q: dangerous

C = []
for _ in range(K):
  C.append(int(input()))
# C[i] = zombie cities

# M rows
adj = [ [] for _ in range(N+1) ]
for _ in range(M):
  a,b = map(int,input().split())
  adj[a].append(b)
  adj[b].append(a)

expensive_cities = set()
for c in C:
  q = deque([c])
  step = 0
  visited = [False] * (N+1)

  while q and step <= S:
    l = len(q)
    new_q = deque()

    for _ in range(l):
      node = q.popleft()
      visited[node] = True

      for nei in adj[node]:
        if visited[nei]: continue
        if nei in q or nei in new_q: continue
        if nei in C: continue
        new_q.append(nei)
    
    q = new_q
    step += 1

  for i in range(1, N+1):
    if visited[i] and i not in C:
      expensive_cities.add(i)

# print(expensive_cities)

adj2 = [ [] for _ in range(N+1) ]
for i in range(1, N+1):
  for city in adj[i]:
    if city in C: continue
    if city in expensive_cities:
      adj2[i].append((city,Q))
    else:
      adj2[i].append((city,P))

# print(adj2)

pq = [(0,1)]
dist = [float('inf')] * (N+1)
visited = [False] * (N+1)
dist[1] = 0
while pq:
  d,n = heapq.heappop(pq)
  if n==N: break
  visited[n] = True

  for nei,nd in adj2[n]:
    # import pdb; pdb.set_trace()
    if visited[nei]: continue
    if d+nd < dist[nei]:
      dist[nei] = d+nd
      heapq.heappush(pq, (d+nd,nei))

# print(dist)
d = dist[N]
if N in expensive_cities:
  print(d-Q)
else:
  print(d-P)

Submission status: Accepted

Solution code:
from collections import deque
from heapq import heappush, heappop
N, M, K, S = map(int, input().split())
P, Q = map(int, input().split())
C = [int(input())-1 for i in range(K)]
G = [[] for i in range(N)]
for i in range(M):
    a, b = map(int, input().split()); a -= 1; b -= 1
    G[a].append(b)
    G[b].append(a)

D = [N]*N
que = deque()
for c in C:
    D[c] = 0
    que.append(c)
while que:
    v = que.popleft()
    d = D[v]
    for w in G[v]:
        if D[w] != N:
            continue
        D[w] = d+1
        que.append(w)

INF = 10**18
dist = [INF]*N
dist[0] = 0
que = [(0, 0)]
while que:
    cost, v = heappop(que)
    if dist[v] < cost:
        continue
    c += 1
    for w in G[v]:
        if D[w] == 0:
            continue
        if D[w] <= S:
            if cost + Q < dist[w]:
                dist[w] = cost + Q
                heappush(que, (cost + Q, w))
        else:
            if cost + P < dist[w]:
                dist[w] = cost + P
                heappush(que, (cost + P, w))
print(dist[N-1] - (Q if D[N-1] <= S else P))