Problem:


Score : 500 points

Problem Statement

There are N cities numbered 1 to N, connected by M railroads.

You are now at City 1, with 10^{100} gold coins and S silver coins in your pocket.

The i-th railroad connects City U_i and City V_i bidirectionally, and a one-way trip costs A_i silver coins and takes B_i minutes.
You cannot use gold coins to pay the fare.

There is an exchange counter in each city. At the exchange counter in City i, you can get C_i silver coins for 1 gold coin.
The transaction takes D_i minutes for each gold coin you give.
You can exchange any number of gold coins at each exchange counter.

For each t=2, ..., N, find the minimum time needed to travel from City 1 to City t. You can ignore the time spent waiting for trains.

Constraints

2 \leq N \leq 50

N-1 \leq M \leq 100

0 \leq S \leq 10^9

1 \leq A_i \leq 50

1 \leq B_i,C_i,D_i \leq 10^9

1 \leq U_i < V_i \leq N

There is no pair i, j(i \neq j) such that (U_i,V_i)=(U_j,V_j).

Each city t=2,...,N can be reached from City 1 with some number of railroads.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M S
U_1 V_1 A_1 B_1
:
U_M V_M A_M B_M
C_1 D_1
:
C_N D_N

Output

For each t=2, ..., N in this order, print a line containing the minimum time needed to travel from City 1 to City t.

Sample Input 1

3 2 1
1 2 1 2
1 3 2 4
1 11
1 2
2 5

Sample Output 1

2
14

The railway network in this input is shown in the figure below.

In this figure, each city is labeled as follows:

The first line: the ID number i of the city (i for City i)

The second line: C_i / D_i

Similarly, each railroad is labeled as follows:

The first line: the ID number i of the railroad (i for the i-th railroad in input)

The second line: A_i / B_i

You can travel from City 1 to City 2 in 2 minutes, as follows:

Use the 1-st railroad to move from City 1 to City 2 in 2 minutes.

You can travel from City 1 to City 3 in 14 minutes, as follows:

Use the 1-st railroad to move from City 1 to City 2 in 2 minutes.

At the exchange counter in City 2, exchange 3 gold coins for 3 silver coins in 6 minutes.

Use the 1-st railroad to move from City 2 to City 1 in 2 minutes.

Use the 2-nd railroad to move from City 1 to City 3 in 4 minutes.

Sample Input 2

4 4 1
1 2 1 5
1 3 4 4
2 4 2 2
3 4 1 1
3 1
3 1
5 2
6 4

Sample Output 2

5
5
7

The railway network in this input is shown in the figure below:

You can travel from City 1 to City 4 in 7 minutes, as follows:

At the exchange counter in City 1, exchange 2 gold coins for 6 silver coins in 2 minutes.

Use the 2-nd railroad to move from City 1 to City 3 in 4 minutes.

Use the 4-th railroad to move from City 3 to City 4 in 1 minutes.

Sample Input 3

6 5 1
1 2 1 1
1 3 2 1
2 4 5 1
3 5 11 1
1 6 50 1
1 10000
1 3000
1 700
1 100
1 1
100 1

Sample Output 3

1
9003
14606
16510
16576

The railway network in this input is shown in the figure below:

You can travel from City 1 to City 6 in 16576 minutes, as follows:

Use the 1-st railroad to move from City 1 to City 2 in 1 minute.

At the exchange counter in City 2, exchange 3 gold coins for 3 silver coins in 9000 minutes.

Use the 1-st railroad to move from City 2 to City 1 in 1 minute.

Use the 2-nd railroad to move from City 1 to City 3 in 1 minute.

At the exchange counter in City 3, exchange 8 gold coins for 8 silver coins in 5600 minutes.

Use the 2-nd railroad to move from City 3 to City 1 in 1 minute.

Use the 1-st railroad to move from City 1 to City 2 in 1 minute.

Use the 3-rd railroad to move from City 2 to City 4 in 1 minute.

At the exchange counter in City 4, exchange 19 gold coins for 19 silver coins in 1900 minutes.

Use the 3-rd railroad to move from City 4 to City 2 in 1 minute.

Use the 1-st railroad to move from City 2 to City 1 in 1 minute.

Use the 2-nd railroad to move from City 1 to City 3 in 1 minute.

Use the 4-th railroad to move from City 3 to City 5 in 1 minute.

At the exchange counter in City 5, exchange 63 gold coins for 63 silver coins in 63 minutes.

Use the 4-th railroad to move from City 5 to City 3 in 1 minute.

Use the 2-nd railroad to move from City 3 to City 1 in 1 minute.

Use the 5-th railroad to move from City 1 to City 6 in 1 minute.

Sample Input 4

4 6 1000000000
1 2 50 1
1 3 50 5
1 4 50 7
2 3 50 2
2 4 50 4
3 4 50 3
10 2
4 4
5 5
7 7

Sample Output 4

1
3
5

The railway network in this input is shown in the figure below:

Sample Input 5

2 1 0
1 2 1 1
1 1000000000
1 1

Sample Output 5

1000000001

The railway network in this input is shown in the figure below:

You can travel from City 1 to City 2 in 1000000001 minutes, as follows:

At the exchange counter in City 1, exchange 1 gold coin for 1 silver coin in 1000000000 minutes.

Use the 1-st railroad to move from City 1 to City 2 in 1 minute.



Sample input:
3 2 1
1 2 1 2
1 3 2 4
1 11
1 2
2 5


Sample output:
2
14

Submission status: Accepted

Solution code:
from collections import defaultdict
import heapq as hq
n,m,s = map(int,input().split())
edges = [[] for _ in range(n+1)]
INF = float('inf')
limit = 0
for i in range(m):
    u,v,a,b = map(int,input().split())
    edges[u].append((v,a,b))
    edges[v].append((u,a,b))
    limit += a
if s > limit:
    s = limit
exchanges = [0]
for i in range(n):
    c,d = map(int,input().split())
    exchanges.append((c,d))
dp = [[INF]*(limit+1) for _ in range(n+1)]
q = []
hq.heapify(q)
hq.heappush(q,(0,1,s))
dp[1][s] = 0
while q:
    time,place,silver = hq.heappop(q)
    c,d = exchanges[place]
    if silver + c <= limit:
        if time+d < dp[place][silver+c]:
            dp[place][silver+c] = time+d
            hq.heappush(q,(time+d,place,silver+c))
    else:
        if time+d < dp[place][limit]:
            dp[place][limit] = time+d
            hq.heappush(q,(time+d,place,limit))
    for v,a,b in edges[place]:
        if silver-a >= 0 and dp[v][silver-a] > time+b:
            dp[v][silver-a] = time+b
            hq.heappush(q,(time+b,v,silver-a))

for i in dp[2:]:
    print(min(i))

Submission status: Accepted

Solution code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging

handler = logging.FileHandler(filename="log")
handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)8s %(message)s'))
logger = logging.getLogger(__name__)
logger.addHandler(handler)

#logger.warn('hello warn')
#logger.error('hello error')
#logger.info('hello info')
#logger.debug('hello debug')


from pprint import pprint as pp
from pprint import pformat as pf
import math


from heapq import heappush, heappop
class PriorityQueue:

    def __init__(self):
        self.contaier = []

    def push(self, time, city, money):
        heappush(self.contaier, (time, (city, money)))

    def pop(self):
        time, taple = heappop(self.contaier)
        return time, taple[0], taple[1]

    def is_empty(self):
        return len(self.contaier) == 0

class Data:

    def __init__(self, money, time):
        self.money = money
        self.time = time

    def __repr__(self):
        return "money {} time {}".format(self.money, self.time)


class Path:
    def __init__(self, frm, to):
        self.frm = frm
        self.to = to

def get_line_info(num_city, num_line):
    line_info = {}
    for i in range(num_city):
        line_info[i] = {}
    for i in range(num_line):
        frm, to, money, time = map(int, input().split())
        frm -= 1
        to -= 1
        line_info[frm][to] = Data(money, time)
        line_info[to][frm] = line_info[frm][to]
    return line_info

class Person:

    def __init__(self, num_city, city_info, line_info):
        #print('city_info') # debug
        #print(city_info) # debug
        #print('line_info') # debug
        #pp(line_info) # debug
        self.city_info = city_info
        self.line_info = line_info
        self.que = PriorityQueue()
        self.dp = [None] * num_city # [city][money] = min time
        self.max_money = (50 * num_city)
        for i in range(num_city):
            self.dp[i] = [math.inf] * (self.max_money + 5)

    def travel(self, money):
        money = min(money, self.max_money)
        self.que.push(0, 0, money)
        while not self.que.is_empty():
            time, city, money = self.que.pop()
            #print('time, city, money') # debug
            #print(time, city, money) # debug
            self.exchange(time, city, money)
            self.walk_around(time, city, money)

    def exchange(self, time, city, money):
        time += self.city_info[city].time
        money += self.city_info[city].money
        self.save_and_push(time, city, money)

    def walk_around(self, time, city, money):
        for to in self.line_info[city]:
            self.walk(city, to, time, money)

    def walk(self, frm, to, time, money):
        time += self.line_info[frm][to].time
        money -= self.line_info[frm][to].money
        self.save_and_push(time, to, money)

    def save_and_push(self, time, city, money):
        if money < 0:
            return
        if not (money < len(self.dp[0])):
            return
        if time < self.dp[city][money]:
            self.dp[city][money] = time
            self.que.push(time, city, money)

    def print_ans(self):
        for city_dp in self.dp[1:]:
            print(min(city_dp))




if __name__ == '__main__':
    num_city, num_line, first_money = map(int, input().split())
    line_info = get_line_info(num_city, num_line)
    city_info = [None] * num_city
    for i in range(num_city):
        money, time = map(int, input().split())
        city_info[i] = Data(money, time)
    p = Person(num_city, city_info, line_info)
    p.travel(first_money)
    p.print_ans()

Submission status: Accepted

Solution code:
import sys
input = lambda : sys.stdin.readline().rstrip()

import heapq
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = {u: [] for u in range(n)}
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns[u-1].append(v-1)
    ns[v-1].append(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     print(dd, u, ss)
    if ans[u][ss] is not None and ans[u][ss] <= dd:
        continue
    ans[u][ss] = dd
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or ans[v][ss-a[e]] is not None:
            continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        heapq.heappush(h, (dd + d[u], u, ss+c[u]))
    elif ss < maxs:
        heapq.heappush(h, (dd + d[u], u, maxs))

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:
import sys
input = lambda : sys.stdin.readline().rstrip()

import heapq
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = {u: set() for u in range(n)}
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns[u-1].add(v-1)
    ns[v-1].add(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     print(dd, u, ss)
    if ans[u][ss] is not None and ans[u][ss] <= dd:
        continue
    ans[u][ss] = dd
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or ans[v][ss-a[e]] is not None:
            continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        heapq.heappush(h, (dd + d[u], u, ss+c[u]))
    elif ss < maxs:
        heapq.heappush(h, (dd + d[u], u, maxs))

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:
import sys
input = lambda : sys.stdin.readline().rstrip()

import heapq
from collections import defaultdict
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = defaultdict(set)
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns[u-1].add(v-1)
    ns[v-1].add(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     print(dd, u, ss)
    if ans[u][ss] is not None and ans[u][ss] <= dd:
        continue
    ans[u][ss] = dd
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or ans[v][ss-a[e]] is not None:
            continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        heapq.heappush(h, (dd + d[u], u, ss+c[u]))
    elif ss < maxs:
        heapq.heappush(h, (dd + d[u], u, maxs))

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:
import sys
input = lambda : sys.stdin.readline().rstrip()

import heapq
from collections import defaultdict
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = defaultdict(list)
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns[u-1].append(v-1)
    ns[v-1].append(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     print(dd, u, ss)
    if ans[u][ss] is not None and ans[u][ss] <= dd:
        continue
    ans[u][ss] = dd
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or ans[v][ss-a[e]] is not None:
            continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        heapq.heappush(h, (dd + d[u], u, ss+c[u]))
    elif ss < maxs:
        heapq.heappush(h, (dd + d[u], u, maxs))

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:
import sys
input = lambda : sys.stdin.readline().rstrip()

import heapq
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = {u: [] for u in range(n)}
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns[u-1].append(v-1)
    ns[v-1].append(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
ans[0][s] = 0
done = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     if ans[u][ss] is not None and ans[u][ss] <= dd:
#         continue
#     ans[u][ss] = dd
    
    if done[u][ss]:
        continue
    done[u][ss] = True
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or done[v][ss-a[e]] :
            continue
        ans[v][ss-a[e]] = min(ans[v][ss-a[e]], dd + b[e]) if ans[v][ss-a[e]] is not None else dd+b[e]
#         if ss<a[e] or ans[v][ss-a[e]] is not None:
#             continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        sss = ss+c[u]
    elif ss < maxs:
        sss = maxs
    else:
        continue
    heapq.heappush(h, (dd + d[u], u, sss))
#     print(sss, maxs, ss, c[u])
    ans[u][sss] = min(ans[u][sss], dd + d[u]) if ans[u][sss] is not None else dd+d[u]

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:
import sys
input = lambda : sys.stdin.readline().rstrip()

import heapq
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = {u: set() for u in range(n)}
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns[u-1].add(v-1)
    ns[v-1].add(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
ans[0][s] = 0
done = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     if ans[u][ss] is not None and ans[u][ss] <= dd:
#         continue
#     ans[u][ss] = dd
    
    if done[u][ss]:
        continue
    done[u][ss] = True
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or done[v][ss-a[e]] :
            continue
        ans[v][ss-a[e]] = min(ans[v][ss-a[e]], dd + b[e]) if ans[v][ss-a[e]] is not None else dd+b[e]
#         if ss<a[e] or ans[v][ss-a[e]] is not None:
#             continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        sss = ss+c[u]
    elif ss < maxs:
        sss = maxs
    else:
        continue
    heapq.heappush(h, (dd + d[u], u, sss))
#     print(sss, maxs, ss, c[u])
    ans[u][sss] = min(ans[u][sss], dd + d[u]) if ans[u][sss] is not None else dd+d[u]

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:

import sys
input = lambda : sys.stdin.readline().rstrip()

import heapq
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = {}
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns.setdefault(u-1, set())
    ns.setdefault(v-1, set())
    ns[u-1].add(v-1)
    ns[v-1].add(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
ans[0][s] = 0
done = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     if ans[u][ss] is not None and ans[u][ss] <= dd:
#         continue
#     ans[u][ss] = dd
    
    if done[u][ss]:
        continue
    done[u][ss] = True
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or done[v][ss-a[e]] :
            continue
        ans[v][ss-a[e]] = min(ans[v][ss-a[e]], dd + b[e]) if ans[v][ss-a[e]] is not None else dd+b[e]
#         if ss<a[e] or ans[v][ss-a[e]] is not None:
#             continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        sss = ss+c[u]
    elif ss < maxs:
        sss = maxs
    else:
        continue
    heapq.heappush(h, (dd + d[u], u, sss))
#     print(sss, maxs, ss, c[u])
    ans[u][sss] = min(ans[u][sss], dd + d[u]) if ans[u][sss] is not None else dd+d[u]

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:

import sys
input = lambda : sys.stdin.readline().rstrip()

import heapq
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = {}
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns.setdefault(u-1, set())
    ns.setdefault(v-1, set())
    ns[u-1].add(v-1)
    ns[v-1].add(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     print(dd, u, ss)
    if ans[u][ss] is not None and ans[u][ss] <= dd:
        continue
    ans[u][ss] = dd
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or ans[v][ss-a[e]] is not None:
            continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        heapq.heappush(h, (dd + d[u], u, ss+c[u]))
    elif ss < maxs:
        heapq.heappush(h, (dd + d[u], u, maxs))

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:

import sys
input = lambda : sys.stdin.readline().rstrip()

import heapq
from collections import defaultdict
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = defaultdict(list)
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns[u-1].append(v-1)
    ns[v-1].append(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     print(dd, u, ss)
    if ans[u][ss] is not None and ans[u][ss] <= dd:
        continue
    ans[u][ss] = dd
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or ans[v][ss-a[e]] is not None:
            continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        heapq.heappush(h, (dd + d[u], u, ss+c[u]))
    elif ss < maxs:
        heapq.heappush(h, (dd + d[u], u, maxs))

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:


import heapq
from collections import defaultdict
h = []
heapq.heapify(h)

n, m, s = list(map(int, input().split()))
a, b = [[None] * m for _ in range(2)]
c, d = [[None] * n for _ in range(2)]

ns = defaultdict(list)
uv2e = {}
for i in range(m):
    u,v,a[i],b[i] = list(map(int, input().split()))
    ns[u-1].append(v-1)
    ns[v-1].append(u-1)
    uv2e[u-1,v-1] = i
    uv2e[v-1,u-1] = i
for i in range(n):
    c[i], d[i] = list(map(int, input().split()))

maxs = max(a)*(n-1)
s = min(s, maxs)
state = (0, 0, s) # (距離, ノード, 銀貨枚数)
ans = [[None] * (maxs+1) for _ in range(n)]
heapq.heappush(h, state)
count = 0
while h:
    count += 1
    dd, u, ss = heapq.heappop(h)
#     print(dd, u, ss)
    if ans[u][ss] is not None and ans[u][ss] <= dd:
        continue
    ans[u][ss] = dd
    
    # グラフの隣接点
    for v in ns[u]:
        e= uv2e[u,v]
        if ss<a[e] or ans[v][ss-a[e]] is not None:
            continue
        heapq.heappush(h, (dd + b[e], v, ss-a[e]))
    # 両替
    if ss+c[u] <= maxs:
        heapq.heappush(h, (dd + d[u], u, ss+c[u]))
    elif ss < maxs:
        heapq.heappush(h, (dd + d[u], u, maxs))

for item in ans[1:]:
    print(min(item))

Submission status: Accepted

Solution code:
import numpy as np
from scipy.sparse import lil_matrix, csr_matrix
from scipy.sparse.csgraph import shortest_path
M=49*50+1
n,m,s=map(int,input().split())
s=min(s,M-1)
G=lil_matrix((n*M,n*M))
for _ in range(m):
    a,b,silver,time=map(int,input().split())
    a-=1
    b-=1
    for i in range(silver,M):
        G[a*M+i,b*M+i-silver]=time
        G[b*M+i,a*M+i-silver]=time
for i in range(n):
    silver,time=map(int,input().split())
    for j in range(M-silver):
        G[i*M+j,i*M+j+silver]=time
G=G.tocsr()
G=shortest_path(G,method='D',indices=s) # D=VlogE ndarray

for i in range(1,n):
    ans=np.min(G[i*M:i*M+M])
    print(int(ans))

Submission status: Accepted

Solution code:
import numpy as np
from scipy.sparse import lil_matrix, csr_matrix
from scipy.sparse.csgraph import shortest_path
M=49*50+1
n,m,s=map(int,input().split())
s=min(s,M-1)
G=lil_matrix((n*M,n*M))
for _ in range(m):
    a,b,silver,time=map(int,input().split())
    a-=1
    b-=1
    for i in range(silver,M):
        G[a*M+i,b*M+i-silver]=time
        G[b*M+i,a*M+i-silver]=time
for i in range(n):
    silver,time=map(int,input().split())
    for j in range(M-1):
        G[i*M+j,i*M+min(j+silver,M-1)]=time
G=G.tocsr()
G=shortest_path(G,method='D',indices=s)

for i in range(1,n):
    ans=np.min(G[i*M:i*M+M])
    print(int(ans))

Submission status: Accepted

Solution code:
n, m, s = map(int, input().split())

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

banks = tuple(tuple(map(int, input().split())) for _ in range(n))

max_s = 50 * (n-1)

s = min(s, max_s)

import heapq

h = []
dp = [[float('inf')] * (max_s+1) for _ in range(n)]
ans = [float('inf')] * n

heapq.heappush(h, (0, 0, s))
while h:
    time, node, coin = heapq.heappop(h)
    if time >= dp[node][coin]:
        continue
    dp[node][coin] = time
    if time < ans[node]:
        ans[node] = time

    c, d = banks[node]
    if coin < max_s:
        heapq.heappush(h, (time+d, node, min(coin + c, max_s)))

    for n, a, b in edges[node]:
        new_time = time + b
        new_coin = coin - a
        if new_coin < 0 or new_time >= dp[n][new_coin]:
            continue
        heapq.heappush(h, (new_time, n, new_coin))

for a in ans[1:]:
    print(a)

Submission status: Accepted

Solution code:
def main():
    import heapq

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

    edges = [[] for _ in range(n)]
    max_cost = 0
    for _ in range(m):
        from_, to, cost, time = map(int, input().split())
        edges[from_-1].append((to-1, cost, time))
        edges[to-1].append((from_-1, cost, time))
        if cost > max_cost:
            max_cost = cost

    banks = []
    for i in range(n):
        coin, time = map(int, input().split())
        banks.append((coin, time))

    max_coin = max_cost * (n-1)
    if s > max_coin:
        s = max_coin

    INF = float('INF')
    DP = [[INF] * (max_coin+1) for _ in range(n)]
    DP[0][s] = 0

    def push_todo(node, coin, time):
        if coin < 0:
            return
        if time >= DP[node][coin]:
            return
        heapq.heappush(todo, (time, node, coin))
        DP[node][coin] = time

    def charge(node, current_coin, current_time):
        coin, time = banks[node]
        new_coin = current_coin + coin
        if new_coin > max_coin:
            new_coin = max_coin
        push_todo(node, new_coin, current_time+time)

    todo = [(0, 0, s)]  # time, node, coin
    while todo:
        current_time, node, current_coin = heapq.heappop(todo)
        if current_time > DP[node][current_coin]:
            continue

        charge(node, current_coin, current_time)

        for to, cost, time in edges[node]:
            push_todo(to, current_coin-cost, current_time+time)

    for node in range(1, n):
        print(min(DP[node]))


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
def main():
    import heapq

    n, m, s = map(int, input().split())
    if s >= 2500:
        s = 2499

    edges = [[] for _ in range(n)]
    for _ in range(m):
        from_, to, cost, time = map(int, input().split())
        edges[from_-1].append((to-1, cost, time))
        edges[to-1].append((from_-1, cost, time))

    banks = []
    for i in range(n):
        coin, time = map(int, input().split())
        banks.append((coin, time))

    INF = float('INF')
    DP = [[INF] * 2500 for _ in range(n)]
    DP[0][s] = 0
    ans = [INF] * n

    def push_todo(node, coin, time):
        if coin < 0:
            return
        if time >= DP[node][coin]:
            return
        heapq.heappush(todo, (time, node, coin))
        DP[node][coin] = time

    def charge(node, current_coin, current_time):
        coin, time = banks[node]
        new_coin = current_coin + coin
        if new_coin >= 2500:
            new_coin = 2499
        push_todo(node, new_coin, current_time+time)

    todo = [(0, 0, s)]  # time, node, coin
    while todo:
        current_time, node, current_coin = heapq.heappop(todo)
        if current_time > DP[node][current_coin]:
            continue

        if current_time < ans[node]:
            ans[node] = current_time

        charge(node, current_coin, current_time)

        for to, cost, time in edges[node]:
            push_todo(to, current_coin-cost, current_time+time)

    for a in ans[1:]:
        print(a)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
def main():    
    import heapq
    
    n, m, s = map(int, input().split())
    if s >= 2500:
        s = 2499
    
    edges = [[] for _ in range(n)]
    for _ in range(m):
        from_, to, cost, time = map(int, input().split())
        edges[from_-1].append((to-1, cost, time))
        edges[to-1].append((from_-1, cost, time))
    
    banks = []
    for i in range(n):
        coin, time = map(int, input().split())
        banks.append((coin, time))
    
    INF = float('INF')
    DP = [[INF] * 2500 for _ in range(n)]
    ans = [INF] * n
    
    def push_todo(node, coin, time):
        if coin < 0:
            return
        if time >= DP[node][coin]:
            return
        heapq.heappush(todo, (time, node, coin))
    
    def charge(node, current_coin, current_time):
        coin, time = banks[node]
        new_coin = current_coin + coin
        if new_coin >= 2500:
            new_coin = 2499
        push_todo(node, new_coin, current_time+time)
    
    todo = [(0, 0, s)]
    while todo:
        current_time, node, current_coin = heapq.heappop(todo)
        if current_time >= DP[node][current_coin]:
            continue
    
        if current_time < ans[node]:
            ans[node] = current_time
    
        DP[node][current_coin] = current_time
        charge(node, current_coin, current_time)
    
        for to, cost, time in edges[node]:
            push_todo(to, current_coin-cost, current_time+time)
    
    for a in ans[1:]:
        print(a)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
import heapq


n, m, s = map(int, input().split())
if s >= 2500:
    s = 2499

edges = [[] for _ in range(n)]
for _ in range(m):
    from_, to, cost, time = map(int, input().split())
    edges[from_-1].append((to-1, cost, time))
    edges[to-1].append((from_-1, cost, time))

banks = []
for i in range(n):
    coin, time = map(int, input().split())
    banks.append((coin, time))

INF = float('INF')
DP = [[INF] * 2500 for _ in range(n)]
ans = [INF] * n


def push_todo(node, coin, time):
    if coin < 0:
        return
    if time >= DP[node][coin]:
        return
    heapq.heappush(todo, (time, node, coin))


def charge(node, current_coin, current_time):
    coin, time = banks[node]
    new_coin = current_coin + coin
    if new_coin >= 2500:
        new_coin = 2499
    push_todo(node, new_coin, current_time+time)


todo = [(0, 0, s)]
while todo:
    current_time, node, current_coin = heapq.heappop(todo)
    if current_time >= DP[node][current_coin]:
        continue

    if current_time < ans[node]:
        ans[node] = current_time

    DP[node][current_coin] = current_time
    charge(node, current_coin, current_time)

    for to, cost, time in edges[node]:
        push_todo(to, current_coin-cost, current_time+time)

for a in ans[1:]:
    print(a)