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: Time Limit Exceeded

Solution code:
import heapq

N, M, S = map(int, input().split())
Cost = [[[-1, -1] for _ in range(N)] for _ in range(N)]
Change = [[0]*2 for _ in range(N)]
A_m = 0
for i in range(M):
    u, v, a, b = map(int, input().split())
    A_m = max(A_m, a)
    Cost[u-1][v-1][0] = a
    Cost[u-1][v-1][1] = b
    Cost[v-1][u-1][0] = a
    Cost[v-1][u-1][1] = b
for i in range(N):
    c, d = map(int, input().split())
    Change[i][0] = c
    Change[i][1] = d
if S > A_m*N:
    S = A_m*N

def dijkstra(N, start, Cost, Change):
    Ans = [10**12]*N
    Ans[0] = 0
    minHeap = []
    used = [[10**12]*(A_m*N + 1) for _ in range(N)]
    used[start][S] = 0
    heapq.heappush(minHeap, (0, S, start))
    while minHeap:
        (c, hold, current) = heapq.heappop(minHeap)
        j = 1
        for i in range(N):
            if Ans[i] > c:
                j = 0
                break
        if j == 1:
            break
        for road in range(N):
            if Cost[current][road][0] != -1:
                if hold >= Cost[current][road][0]:
                    if used[road][hold - Cost[current][road][0]] > c + Cost[current][road][1]:
                        used[road][hold - Cost[current][road][0]] = c + Cost[current][road][1]
                        heapq.heappush(minHeap, (c + Cost[current][road][1], hold - Cost[current][road][0], road))
                    if Ans[road] > c + Cost[current][road][1]:
                        Ans[road] = c + Cost[current][road][1]
        if hold + Change[current][0] <= A_m*N:
            if used[current][hold + Change[current][0]] > c + Change[current][1]:
                heapq.heappush(minHeap, (c + Change[current][1], hold + Change[current][0], current))
    return Ans

T = dijkstra(N, 0, Cost, Change)
for i in T[1:]:
    print(i)

Submission status: Time Limit Exceeded

Solution code:
import heapq

N, M, S = map(int, input().split())
Cost = [[[-1, -1] for _ in range(N)] for _ in range(N)]
Change = [[0]*2 for _ in range(N)]
for i in range(M):
    u, v, a, b = map(int, input().split())
    Cost[u-1][v-1][0] = a
    Cost[u-1][v-1][1] = b
    Cost[v-1][u-1][0] = a
    Cost[v-1][u-1][1] = b
for i in range(N):
    c, d = map(int, input().split())
    Change[i][0] = c
    Change[i][1] = d
if S > 2500:
    S = 2500

def dijkstra(N, start, Cost, Change, S):
    minHeap = []
    used = [[10**12]*2501 for _ in range(N)]
    used[start][S] = 0
    heapq.heappush(minHeap, (0, S, start))
    while minHeap:
        (c, hold, current) = heapq.heappop(minHeap)
        for road in range(N):
            if Cost[current][road][0] != -1:
                if hold >= Cost[current][road][0]:
                    if used[road][hold - Cost[current][road][0]] > c + Cost[current][road][1]:
                        used[road][hold - Cost[current][road][0]] = c + Cost[current][road][1]
                        heapq.heappush(minHeap, (c + Cost[current][road][1], hold - Cost[current][road][0], road))
        if hold + Change[current][0] <= 2500:
            if used[current][hold + Change[current][0]] > c + Change[current][1]:
                heapq.heappush(minHeap, (c + Change[current][1], hold + Change[current][0], current))
    return used

T = dijkstra(N, 0, Cost, Change, S)
for i in T[1:]:
    print(min(i))

Submission status: Time Limit Exceeded

Solution code:
import heapq

# https://nashidos.hatenablog.com/entry/2020/04/07/100508
def dijkstra(s):
    hq = [(0, s)]
    heapq.heapify(hq) # リストを優先度付きキューに変換
    cost = [float('inf')] * ((maxsilver+1)*n) # 行ったことのないところはinf
    cost[s] = 0 # 開始地点は0
    while hq:
        c, v = heapq.heappop(hq)
        if c > cost[v]: # コストが現在のコストよりも高ければスルー
            continue
        for d, w in e[v]:
            tmp = d + cost[v]
            if tmp < cost[w]:
                cost[w] = tmp
                heapq.heappush(hq, (tmp, w))
    return cost

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

u,v,a,b = [0]*m,[0]*m,[0]*m,[0]*m 
c,d = [0]*n,[0]*n 
for i in range(m):
    u[i],v[i],a[i],b[i] = list(map(int,input().split()))
for i in range(n):
    c[i],d[i] = list(map(int,input().split()))

maA = max(a)
maxsilver = maA*(n-1)
p = (maxsilver+1) * n
# 都市i(0~)で銀貨j枚持っている時,i*(maxsilver+1)+j番目
e = [[] for i in range(p)]
# 金貨交換
for i in range(n):
    for j in range(maxsilver+1):
        e[i*(maxsilver+1) + j].append((d[i], i*(maxsilver+1) + min(j+c[i], maxsilver)))
# 移動
for i in range(m):
    for j in range(a[i],maxsilver+1):
        e[(u[i]-1)*(maxsilver+1) + j].append((b[i], (v[i]-1)*(maxsilver+1) + j-a[i]))
        e[(v[i]-1)*(maxsilver+1) + j].append((b[i], (u[i]-1)*(maxsilver+1) + j-a[i]))

# print(e)
# 初期地点は0+min(s,maxsilver)
for i in range(1,n):
    ans = float("inf")
    x = [0]*(maxsilver+1)
    for j in range(maxsilver+1):
        x[j] =  dijkstra(min(s,maxsilver))[i*(maxsilver+1)+j]
    heapq.heapify(x)
    ans = heapq.heappop(x)
    print(ans)

Submission status: Time Limit Exceeded

Solution code:
import heapq

# https://nashidos.hatenablog.com/entry/2020/04/07/100508
def dijkstra(s):
    hq = [(0, s)]
    heapq.heapify(hq) # リストを優先度付きキューに変換
    cost = [float('inf')] * ((maxsilver+1)*n) # 行ったことのないところはinf
    cost[s] = 0 # 開始地点は0
    while hq:
        c, v = heapq.heappop(hq)
        if c > cost[v]: # コストが現在のコストよりも高ければスルー
            continue
        for d, w in e[v]:
            tmp = d + cost[v]
            if tmp < cost[w]:
                cost[w] = tmp
                heapq.heappush(hq, (tmp, w))
    return cost

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

u,v,a,b = [0]*m,[0]*m,[0]*m,[0]*m 
c,d = [0]*n,[0]*n 
for i in range(m):
    u[i],v[i],a[i],b[i] = list(map(int,input().split()))
for i in range(n):
    c[i],d[i] = list(map(int,input().split()))

maA = max(a)
maxsilver = maA*(n-1)
p = (maxsilver+1) * n
# 都市i(0~)で銀貨j枚持っている時,i*(maxsilver+1)+j番目
e = [[] for i in range(p)]
# 金貨交換
for i in range(n):
    for j in range(maxsilver+1):
        e[i*(maxsilver+1) + j].append((d[i], i*(maxsilver+1) + min(j+c[i], maxsilver)))
# 移動
for i in range(m):
    for j in range(a[i],maxsilver+1):
        e[(u[i]-1)*(maxsilver+1) + j].append((b[i], (v[i]-1)*(maxsilver+1) + j-a[i]))
        e[(v[i]-1)*(maxsilver+1) + j].append((b[i], (u[i]-1)*(maxsilver+1) + j-a[i]))

# print(e)
# 初期地点は0+min(s,maxsilver)
for i in range(1,n):
    ans = float("inf")
    for j in range(maxsilver+1):
        ans = min(ans, dijkstra(0+min(s,maxsilver))[i*(maxsilver+1)+j])
    print(ans)

Submission status: Time Limit Exceeded

Solution code:
import heapq

N, M, S = map(int, input().split())
Cost = [[[-1, -1] for _ in range(N)] for _ in range(N)]
Change = [[0]*2 for _ in range(N)]
for i in range(M):
    u, v, a, b = map(int, input().split())
    Cost[u-1][v-1][0] = a
    Cost[u-1][v-1][1] = b
    Cost[v-1][u-1][0] = a
    Cost[v-1][u-1][1] = b
for i in range(N):
    c, d = map(int, input().split())
    Change[i][0] = c
    Change[i][1] = d

def dijkstra(N, start, Cost, Change):
    minHeap = []
    used = [10**12]*N
    used[start] = 0
    heapq.heappush(minHeap, (0, S, start))

    while minHeap:
        (c, hold, current) = heapq.heappop(minHeap)
        j = 1
        for i in range(N):
            if used[i] > c:
                j = 0
                break
        if j == 1:
            break
        for road in range(N):
            if Cost[current][road][0] != -1:
                if used[road] > c + Cost[current][road][1] and hold >= Cost[current][road][0]:
                    used[road] = c + Cost[current][road][1]
                if hold >= Cost[current][road][0]:
                    heapq.heappush(minHeap, (c + Cost[current][road][1], hold - Cost[current][road][0], road))
        if hold + Change[current][0] <= 2500:
            heapq.heappush(minHeap, (c + Change[current][1], hold + Change[current][0], current))
    return used

T = dijkstra(N, 0, Cost, Change)
for i in T[1:]:
    print(i)

Submission status: Time Limit Exceeded

Solution code:
class Graph:
    class Edge:
        def __init__(self, to, cost, fare):
            """
            :param to:  終点ノード
            :param cost: 辺の重み
            """
            self.to, self.cost, self.fare = to, cost, fare

    def __init__(self, n, directed=False, decrement=True, edges=[]):
        self.n = n
        self.directed = directed
        self.decrement = decrement
        self.edges = [[] for _ in range(self.n)]
        self.parent = [-1]*self.n
        self.info = [-1]*self.n
        self.fare_max = 0
        for x, y, cost, fare in edges:
            self.add_edge(x, y, cost, fare)
            if fare > self.fare_max:
                self.fare_max = fare

    def add_edge(self, x, y, cost, fare):
        if self.decrement:
            x -= 1
            y -= 1
        self.edges[x].append(self.Edge(y, cost, fare))
        if self.directed == False:
            self.edges[y].append(self.Edge(x, cost, fare))
        if fare > self.fare_max:
            self.fare_max = fare

    def dijkstra(self, start, S, INF=10**18):
        """
        :param start: スタート地点
        :return: スタート地点から各点への距離のリスト
        備考: heqpq の比較のための key は第一引数である点に注意（ =　heappush(heapq, (key,value))　）
        """
        res = [[INF] * (self.fare_max*self.n+1) for _ in  range(self.n)]
        if self.decrement:
            start -= 1
        money = min2(S, self.fare_max*(self.n-1))
        res[start][money] = 0
        next_set = [(0, start, money)]
        while next_set:
            dist, p, money = heappop(next_set)
            if res[p][money] < dist:
                continue
            if money < self.fare_max*(self.n - 1):
                heappush(next_set, (dist + D[p], p, min2(money + C[p], self.fare_max*(self.n-1))))
            for edge in self.edges[p]:
                q, cost, fare = edge.to, edge.cost, edge.fare
                temp_d = dist + cost
                if temp_d < res[q][money-fare] and money >= fare:
                    res[q][money-fare] = temp_d
                    heappush(next_set, (temp_d, q, money - fare))
        if self.decrement:
            return [[0]] + res
        else:
            return res

def max2(x,y):
    return x if x > y else y

def min2(x,y):
    return x if x < y else y

##############################################################################################################

import sys
input = sys.stdin.readline
from heapq import *
INF = 10**18  # 大きい数字

C, D = [], []
N, M, S = map(int, input().split())

graph = Graph(N, directed=False, decrement=True)
for _ in range(M):
    x, y, fare, cost = map(int, input().split())
    graph.add_edge(x, y, cost, fare)
for _ in range(N):
    c, d = map(int, input().split())
    C.append(c)
    D.append(d)
d = graph.dijkstra(1,S,INF=INF)
for i in range(2,N+1):
    print(min(d[i]))

Submission status: Time Limit Exceeded

Solution code:
import math

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

road = []
for i in range(m):
    u,v,a,b = map(int,input().split())
    road.append([u,v,a,b])

change = []
for i in range(n):
    c,d = map(int,input().split())
    change.append([c,d])

tree = [[] for _ in range(n+1)]

for i in range(m):
    r = road[i]
    tree[r[0]].append([r[0],r[1],r[2],r[3]])
    tree[r[1]].append([r[1],r[0],r[2],r[3]])

least_cost = [[] for _ in range(n+1)]
for l in range(n+1):
    least_cost[l] = [math.inf]*2501


def insort_queue(q,v):
    len_a = len(q)    
    if len_a == 0:
        q.append(v)
        return
    
    min = 0
    max_1 = len_a

    if max_1 == 1:
        if v[2] > q[0][2]:
            min = 1
        else:
            min = 0
    while max_1 - min > 1:
        mid = (max_1 + min) //2
        if v[2] > q[mid][2]:
            min = mid
        else:
            max_1 = mid
    index = max_1
    q.insert(index,v)

queue = []

#hwd [location, money, time]
def dijakstra(q):
    while q != []:
        hwd = q.pop(0)
        
        if least_cost[hwd[0]][hwd[1]] > hwd[2]:
            least_cost[hwd[0]][hwd[1]] = hwd[2]
            
            for node in tree[hwd[0]]:
                # from node, to node , money, time
                if hwd[1] - node[2] >= 0:
                    insort_queue(q,[node[1],hwd[1]-node[2],hwd[2]+node[3]])
            if hwd[1] + change[hwd[0]-1][0] <= 2500:
                insort_queue(q,[hwd[0],hwd[1]+change[hwd[0]-1][0],hwd[2]+change[hwd[0]-1][1]])
    return least_cost

if s > 2500:
    s = 2500
queue.append([1,s,0])

ans = dijakstra(queue)

for i in range(2,n+1):
    print(min(ans[i]))

Submission status: Time Limit Exceeded

Solution code:
import math

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

road = []
for i in range(m):
    u,v,a,b = map(int,input().split())
    road.append([u,v,a,b])

change = []
for i in range(n):
    c,d = map(int,input().split())
    change.append([c,d])

tree = [[] for _ in range(n+1)]

for i in range(m):
    r = road[i]
    tree[r[0]].append([r[0],r[1],r[2],r[3]])
    tree[r[1]].append([r[1],r[0],r[2],r[3]])

least_cost = [[] for _ in range(n+1)]
for l in range(n+1):
    least_cost[l] = [math.inf]*2501


def insort_queue(q,v):
    len_a = len(q)    
    if len_a == 0:
        q.append(v)
        return
    
    min = 0
    max_1 = len_a

    if max_1 == 1:
        if v[2] > q[0][2]:
            min = 1
        else:
            min = 0
    while max_1 - min > 1:
        mid = (max_1 + min) //2
        if v[2] > q[mid][2]:
            min = mid
        else:
            max_1 = mid
    index = max_1
    q.insert(index,v)

queue = []

#hwd [location, money, time, n,]
def dijakstra(q):
    while q != []:
        hwd = q.pop(0)
        if hwd[1] < 0 or hwd[1] > 2500:
            continue

        if least_cost[hwd[0]][hwd[1]] > hwd[2]:
            least_cost[hwd[0]][hwd[1]] = hwd[2]
            
            for node in tree[hwd[0]]:
                # from node, to node , money, time
                insort_queue(q,[node[1],hwd[1]-node[2],hwd[2]+node[3]])
            insort_queue(q,[hwd[0],hwd[1]+change[hwd[0]-1][0],hwd[2]+change[hwd[0]-1][1]])
    return least_cost

if s > 2500:
    s = 2500
queue.append([1,s,0])

ans = dijakstra(queue)

for i in range(2,n+1):
    print(min(ans[i]))

Submission status: Time Limit Exceeded

Solution code:
import math

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

road = []
for i in range(m):
    u,v,a,b = map(int,input().split())
    road.append([u,v,a,b])

change = []
for i in range(n):
    c,d = map(int,input().split())
    change.append([c,d])

tree = [[] for _ in range(n+1)]

for i in range(m):
    r = road[i]
    tree[r[0]].append([r[0],r[1],r[2],r[3]])
    tree[r[1]].append([r[1],r[0],r[2],r[3]])

least_cost = [[] for _ in range(n+1)]
for l in range(n+1):
    least_cost[l] = [math.inf]*2501


def insort_queue(q,v):
    len_a = len(q)    
    if len_a == 0:
        q.append(v)
        return
    
    min = 0
    max_1 = len_a

    if max_1 == 1:
        if v[2] > q[0][2]:
            min = 1
        else:
            min = 0
    while max_1 - min > 1:
        mid = (max_1 + min) //2
        if v[2] > q[mid][2]:
            min = mid
        else:
            max_1 = mid
    index = max_1
    q.insert(index,v)

queue = []

#hwd [location, money, time, n,]
def dijakstra(q):
    while q != []:
        hwd = q.pop(0)
        if hwd[1] < 0 or hwd[1] > 2500:
            continue
        
        if least_cost[hwd[0]][hwd[1]] > hwd[2]:
            least_cost[hwd[0]][hwd[1]] = hwd[2]
            
            for node in tree[hwd[0]]:
                # from node, to node , money, time
                insort_queue(q,[node[1],hwd[1]-node[2],hwd[2]+node[3]])
                insort_queue(q,[node[0],hwd[1]+change[node[0]-1][0],hwd[2]+change[node[0]-1][1]])
    return least_cost

if s > 2500:
    s = 2500
queue.append([1,s,0])

ans = dijakstra(queue)

for i in range(2,n+1):
    print(min(ans[i]))

Submission status: Time Limit Exceeded

Solution code:
N,M,S=map(int,input().split())
UVAB=[list(map(int,input().split())) for i in range(M)]
C,D=zip(*[list(map(int,input().split())) for i in range(N)])
c=[[] for i in range(N)]
A=[[] for i in range(N)]
B=[[] for i in range(N)]
for u,v,a,b in UVAB:
    c[u-1].append(v-1)
    c[v-1].append(u-1)
    A[u-1].append(a)
    A[v-1].append(a)
    B[u-1].append(b)
    B[v-1].append(b)
inf=10**20
from heapq import heappop,heappush
X=50*(N-1)
def dij(p,s):
    d=[[inf]*(X+1) for i in range(N)]
    d[p][s]=0
    q=[]
    heappush(q,(0,(p,s)))
    while q:
        t,(p,s)=heappop(q)
        for i in range(1,(X+1-s)//C[p]):
            if X<s+i*C[p] or d[p][s+i*C[p]]<=d[p][s]+i*D[p]:break
            d[p][s+i*C[p]]=d[p][s]+i*D[p]
            heappush(q,(d[p][s]+i*D[p],(p,s+i*C[p])))
        for j,n in enumerate(c[p]):
            if 0<=s-A[p][j] and d[n][s-A[p][j]]>d[p][s]+B[p][j]:
                d[n][s-A[p][j]]=d[p][s]+B[p][j]
                heappush(q,(d[n][s-A[p][j]],(n,s-A[p][j])))
    return d
d=dij(0,min(S,X))
print(*[min(x) for x in d[1:]],sep='\n')

Submission status: Time Limit Exceeded

Solution code:
import heapq
import sys
input = sys.stdin.buffer.readline
sys.setrecursionlimit(10 ** 7)

N, M, S = map(int, input().split())
edge = [[] for _ in range(N)]
for _ in range(M):
    u, v, a, b = map(int, input().split())
    u -= 1
    v -= 1
    edge[u].append((v, a, b))
    edge[v].append((u, a, b))
CD = tuple(tuple(map(int, input().split())) for _ in range(N))

inf = 10**18
U = N*50
S = min(S, U)
dist = [[inf] * (U + 1) for _ in range(N)]
dist[0][S] = 0

que = [(0, -S, 0)]  # 時間、現在地、銀貨の数
while que:
    time, silver, now = heapq.heappop(que)
    silver = -silver
    if dist[now][silver] < time:
        continue
    # 両替する
    c, d = CD[now]
    n = 1
    while silver + c * n <= U:
        if dist[now][silver + c * n] > time + n * d:
            dist[now][silver + c * n] = time + n * d
            heapq.heappush(que, (time + n * d, -(silver + c * n), now))
            n += 1
    # 移動する
    for nxt, s, t in edge[now]:
        if silver < s:
            continue
        if dist[nxt][silver - s] > time + t:
            dist[nxt][silver - s] = time + t
            heapq.heappush(que, (time + t, -(silver - s), nxt))

for i in range(1, N):
    print(min(dist[i]))

Submission status: Time Limit Exceeded

Solution code:
import heapq
import sys
input = sys.stdin.buffer.readline
sys.setrecursionlimit(10 ** 7)

N, M, S = map(int, input().split())
edge = [[] for _ in range(N)]
for _ in range(M):
    u, v, a, b = map(int, input().split())
    u -= 1
    v -= 1
    edge[u].append((v, a, b))
    edge[v].append((u, a, b))
CD = tuple(tuple(map(int, input().split())) for _ in range(N))

inf = 10**18
U = N*50
S = min(S, U)
dist = [[inf] * (U + 1) for _ in range(N)]
dist[0][S] = 0

que = [(0, 0, S)]  # 時間、現在地、銀貨の数
while que:
    time, now, silver = heapq.heappop(que)
    if dist[now][silver] < time:
        continue
    # 両替する
    c, d = CD[now]
    for i in range(1, U + 1):
        if silver + i > U:
            break
        t = (i + c - 1) // c * d
        if dist[now][silver + i] > time + t:
            dist[now][silver + i] = time + t
            heapq.heappush(que, (time + t, now, silver + i))

    # 移動する
    for nxt, s, t in edge[now]:
        if silver < s:
            continue
        if dist[nxt][silver - s] > time + t:
            dist[nxt][silver - s] = time + t
            heapq.heappush(que, (time + t, nxt, silver - s))

for i in range(1, N):
    print(min(dist[i]))

Submission status: Time Limit Exceeded

Solution code:
import heapq
def dijkstra_heap(N,S,edge):
  d = [[float('inf')]*(N*100+1) for _ in range(N)] #始点0から各頂点への最短距離
  used = [[False]*(N*100+1) for _ in range(N)]
  d[0][S] = 0
  used[0][S] = True
  edgelist = []
  #edgelist : [(0,S)からの暫定(未確定)最短時間,頂点,銀貨の枚数]のリスト
  #edge[s] : sから出る枝の[重み,頂点,銀貨の枚数]のリスト
  for w,v,sil in edge[0]:
    if S+sil>=0 and S+sil<=N*100:
      heapq.heappush(edgelist,[w,v,S+sil]) #sの隣の点は枝の重さがそのまま暫定最短距離となる
  while len(edgelist):
    #まだ使われてない頂点の中から最小の距離のものを探す→確定させる
    min_w,min_v,min_sil = heapq.heappop(edgelist)
    #min_w,min_v,min_sil : [0からの(確定)最短距離,頂点,銀貨の枚数]
    if used[min_v][min_sil]:
      continue
    d[min_v][min_sil] = min_w
    used[min_v][min_sil] = True
    for w,v,sil in edge[min_v]:
      if min_sil+sil>=0 and min_sil+sil<=N*100 and not used[v][min_sil+sil]:
        heapq.heappush(edgelist,[min_w+w,v,min_sil+sil])
  return d

def solve():
  N, M, S = map(int, input().split())
  edge = [[] for _ in range(N)]
  amax = 0
  for i in range(M):
    u,v,a,b = map(int, input().split())
    amax = max(amax,a)
    edge[u-1].append([b,v-1,-a])
    edge[v-1].append([b,u-1,-a])
  S = min(S,(N-1)*amax)
  for i in range(N):
    c,d = map(int, input().split())
    edge[i].append([d,i,c])
  D = dijkstra_heap(N,S,edge)
  ans = [0]*N
  for i in range(1,N):
    ans[i] = min(D[i])
  return ans[1:]
print(*solve(),sep='\n')

Submission status: Time Limit Exceeded

Solution code:
import heapq
def dijkstra_heap(N,S,edge):
  S = min(S,5000)
  d = [[float('inf')]*(N*100+1) for _ in range(N)] #始点0から各頂点への最短距離
  used = [[False]*(N*100+1) for _ in range(N)]
  d[0][S] = 0
  used[0][S] = True
  edgelist = []
  #edgelist : [(0,S)からの暫定(未確定)最短時間,頂点,銀貨の枚数]のリスト
  #edge[s] : sから出る枝の[重み,頂点,銀貨の枚数]のリスト
  for w,v,sil in edge[0]:
    if S+sil>=0 and S+sil<=N*100:
      heapq.heappush(edgelist,[w,v,S+sil]) #sの隣の点は枝の重さがそのまま暫定最短距離となる
  while len(edgelist):
    #まだ使われてない頂点の中から最小の距離のものを探す→確定させる
    min_w,min_v,min_sil = heapq.heappop(edgelist)
    #min_w,min_v,min_sil : [0からの(確定)最短距離,頂点,銀貨の枚数]
    if used[min_v][min_sil]:
      continue
    d[min_v][min_sil] = min_w
    used[min_v][min_sil] = True
    for w,v,sil in edge[min_v]:
      if min_sil+sil>=0 and min_sil+sil<=N*100 and not used[v][min_sil+sil]:
        heapq.heappush(edgelist,[min_w+w,v,min_sil+sil])
  return d

def solve():
  N, M, S = map(int, input().split())
  S = min(S,N*100)
  edge = [[] for _ in range(N)]
  for i in range(M):
    u,v,a,b = map(int, input().split())
    edge[u-1].append([b,v-1,-a])
    edge[v-1].append([b,u-1,-a])
  for i in range(N):
    c,d = map(int, input().split())
    edge[i].append([d,i,c])
  D = dijkstra_heap(N,S,edge)
  ans = [0]*N
  for i in range(1,N):
    ans[i] = min(D[i])
  return ans[1:]
print(*solve(),sep='\n')

Submission status: Time Limit Exceeded

Solution code:
import heapq
def dijkstra_heap(N,S,edge):
  S = min(S,5000)
  d = [[float('inf')]*5001 for _ in range(N)] #始点0から各頂点への最短距離
  used = [[False]*5001 for _ in range(N)]
  d[0][S] = 0
  used[0][S] = True
  edgelist = []
  #edgelist : [(0,S)からの暫定(未確定)最短時間,頂点,銀貨の枚数]のリスト
  #edge[s] : sから出る枝の[重み,頂点,銀貨の枚数]のリスト
  for w,v,sil in edge[0]:
    if S+sil>=0 and S+sil<=5000:
      heapq.heappush(edgelist,[w,v,S+sil]) #sの隣の点は枝の重さがそのまま暫定最短距離となる
  while len(edgelist):
    #まだ使われてない頂点の中から最小の距離のものを探す→確定させる
    min_w,min_v,min_sil = heapq.heappop(edgelist)
    #min_w,min_v,min_sil : [0からの(確定)最短距離,頂点,銀貨の枚数]
    if used[min_v][min_sil]:
      continue
    d[min_v][min_sil] = min_w
    used[min_v][min_sil] = True
    for w,v,sil in edge[min_v]:
      if min_sil+sil>=0 and min_sil+sil<=5000 and not used[v][min_sil+sil]:
        heapq.heappush(edgelist,[min_w+w,v,min_sil+sil])
  return d

def solve():
  N, M, S = map(int, input().split())
  edge = [[] for _ in range(N)]
  for i in range(M):
    u,v,a,b = map(int, input().split())
    edge[u-1].append([b,v-1,-a])
    edge[v-1].append([b,u-1,-a])
  for i in range(N):
    c,d = map(int, input().split())
    edge[i].append([d,i,c])
  D = dijkstra_heap(N,S,edge)
  ans = [0]*N
  for i in range(1,N):
    ans[i] = min(D[i])
  return ans[1:]
print(*solve(),sep='\n')

Submission status: Time Limit Exceeded

Solution code:
import heapq
def dijkstra_heap(N,S,edge):
  S = min(S,5000)
  d = [[float('inf')]*5001 for _ in range(N)] #始点0から各頂点への最短距離
  used = [[False]*5001 for _ in range(N)]
  d[0][S] = 0
  used[0][S] = True
  edgelist = []
  #edgelist : [(0,S)からの暫定(未確定)最短時間,頂点,銀貨の枚数]のリスト
  #edge[s] : sから出る枝の[重み,頂点,銀貨の枚数]のリスト
  for w,v,sil in edge[0]:
    if S+sil>=0 and S+sil<=5000:
      heapq.heappush(edgelist,[w,v,S+sil]) #sの隣の点は枝の重さがそのまま暫定最短距離となる
  while len(edgelist):
    #まだ使われてない頂点の中から最小の距離のものを探す→確定させる
    min_w,min_v,min_sil = heapq.heappop(edgelist)
    #min_w,min_v,min_sil : [0からの(確定)最短距離,頂点,銀貨の枚数]
    if used[min_v][min_sil]:
      continue
    d[min_v][min_sil] = min_w
    used[min_v][min_sil] = True
    for w,v,sil in edge[min_v]:
      if min_sil+sil>=0 and min_sil+sil<=5000 and not used[v][min_sil+sil]:
        heapq.heappush(edgelist,[min_w+w,v,min_sil+sil])
  return d

def solve():
  N, M, S = map(int, input().split())
  edge = [[] for _ in range(N)]
  for i in range(M):
    u,v,a,b = map(int, input().split())
    edge[u-1].append([b,v-1,-a])
    edge[v-1].append([b,u-1,-a])
  for i in range(N):
    c,d = map(int, input().split())
    edge[i].append([d,i,c])
  D = dijkstra_heap(N,S,edge)
  ans = [0]*N
  for i in range(1,N):
    ans[i] = min(D[i])
  return ans[1:]
print(*solve(),sep='\n')

Submission status: Time Limit Exceeded

Solution code:
import heapq

city_num, road_num, init_silver = map(int, input().split())
init_silver  = min(2500, init_silver)

G = [[] for _ in range(city_num)]
for _ in range(road_num):
    A, B, cost, time_cost = map(int, input().split())
    A, B = A-1, B-1
    G[B].append([A, cost, time_cost])
    G[A].append([B, cost, time_cost])

for n in range(city_num):
    cost, time_cost = map(int, input().split())
    G[n].append([n, -cost, time_cost])

dp = [[float("inf")] * 2501 for _ in range(city_num)]
dp[0][init_silver] = 0
hq = [(0, 0, init_silver)]
while hq:
    time, node, silver = heapq.heappop(hq)
    for to, silver_cost, time_cost in G[node]:
        remain = min(silver - silver_cost, 2500)
        if remain < 0:
            continue
        dp_next_value = time + time_cost
        if dp[to][remain] <= dp_next_value:
            continue
        dp[to][remain] = dp_next_value
        hq.append([dp_next_value, to, remain])
print(*[min(d) for d in dp[1:]], sep="\n")

Submission status: Time Limit Exceeded

Solution code:
from heapq import heappop, heappush


def main():
    N, M, S = map(int, input().split())
    adj = [{} for _ in range(N)]
    amax = 0
    for _ in range(M):
        u, v, a, b = map(int, input().split())
        adj[u-1][v-1] = (a, b)
        adj[v-1][u-1] = (a, b)
        amax = max(amax, a)
    C = [0] * N
    D = [0] * N
    for i in range(N):
        C[i], D[i] = map(int, input().split())
    MAX = amax * N
    dp = [[float("inf")] * (MAX+1) for _ in range(N)]
    q = [(0, min(S, MAX), 0, -1)]
    ans = [None] * N
    remain = N
    while len(q) and remain:
        time, coin, cur, prev = heappop(q)
        if dp[cur][coin] <= time:
            continue
        if ans[cur] is None:
            ans[cur] = time
            remain -= 1
        dp[cur][coin] = time
        if coin < MAX:
            heappush(q, (time + D[cur], min(coin + C[cur], MAX), cur, cur))
        for nxt in adj[cur]:
            dcost, dtime = adj[cur][nxt]
            if nxt != prev and dcost <= coin:
                heappush(q, (time + dtime, coin - dcost, nxt, cur))
    for i in range(1, N):
        print(ans[i])


if __name__ == "__main__":
    main()