Bicycles (Codeforces 1915G)
Tags: Greedy, shortest paths

All of Slavic's friends are planning to travel from the place where they live to a party using their bikes. And they all have a bike except Slavic. There are $$$n$$$ cities through which they can travel. They all live in the city $$$1$$$ and want to go to the party located in the city $$$n$$$. The map of cities can be seen as an undirected graph with $$$n$$$ nodes and $$$m$$$ edges. Edge $$$i$$$ connects cities $$$u_i$$$ and $$$v_i$$$ and has a length of $$$w_i$$$.Slavic doesn't have a bike, but what he has is money. Every city has exactly one bike for sale. The bike in the $$$i$$$-th city has a slowness factor of $$$s_{i}$$$. Once Slavic buys a bike, he can use it whenever to travel from the city he is currently in to any neighboring city, by taking $$$w_i \cdot s_j$$$ time, considering he is traversing edge $$$i$$$ using a bike $$$j$$$ he owns.Slavic can buy as many bikes as he wants as money isn't a problem for him. Since Slavic hates traveling by bike, he wants to get from his place to the party in the shortest amount of time possible. And, since his informatics skills are quite rusty, he asks you for help.What's the shortest amount of time required for Slavic to travel from city $$$1$$$ to city $$$n$$$? Slavic can't travel without a bike. It is guaranteed that it is possible for Slavic to travel from city $$$1$$$ to any other city.

Input: The first line contains a single integer $$$t$$$ ($$$1 \leq t \leq 100$$$) — the number of test cases. The description of the test cases follows.The first line of each test case contains two space-separated integers $$$n$$$ and $$$m$$$ ($$$2 \leq n \leq 1000$$$; $$$n - 1 \leq m \leq 1000$$$) — the number of cities and the number of roads, respectively.The $$$i$$$-th of the following $$$m$$$ lines each contain three integers $$$u_i$$$, $$$v_i$$$, $$$w_i$$$ ($$$1 \le u_i, v_i \le n$$$, $$$u_i \neq v_i$$$; $$$1 \leq w_i \leq 10^5$$$), denoting that there is a road between cities $$$u_i$$$ and $$$v_i$$$ of length $$$w_i$$$. The same pair of cities can be connected by more than one road.The next line contains $$$n$$$ integers $$$s_1, \ldots, s_n$$$ ($$$1 \leq s_i \leq 1000$$$) — the slowness factor of each bike.The sum of $$$n$$$ over all test cases does not exceed $$$1000$$$, and the sum of $$$m$$$ over all test cases does not exceed $$$1000$$$.Additional constraint on the input: it is possible to travel from city $$$1$$$ to any other city.

Output: For each test case, output a single integer denoting the shortest amount of time Slavic can reach city $$$n$$$ starting from city $$$1$$$.


Sample Inputs:
3
5 5
1 2 2
3 2 1
2 4 5
2 5 7
4 5 1
5 2 1 3 3
5 10
1 2 5
1 3 5
1 4 4
1 5 8
2 3 6
2 4 3
2 5 2
3 4 1
3 5 8
4 5 2
7 2 8 4 1
7 10
3 2 8
2 1 4
2 5 7
2 6 4
7 1 2
4 3 5
6 4 2
6 7 1
6 7 4
4 5 9
7 6 5 4 3 2 1

Sample Outputs:
19
36
14

Solution (Python):
import heapq
INF = 100000000000.0 + 7

def bfs(adj, factors):
    n = len(adj)
    heap = []
    times = [[INF for _ in range(1001)] for _ in adj]
    times[0][factors[0]] = 0
    heapq.heappush(heap, (0, factors[0], 0))
    res = INF
    while heap:
        (time, factor, nd) = heapq.heappop(heap)
        for (nbr, dist) in adj[nd]:
            new_time = time + factor * dist
            new_factor = min(factor, factors[nbr])
            if new_time < times[nbr][new_factor] and new_time < res:
                times[nbr][new_factor] = new_time
                if nbr == n - 1:
                    res = new_time
                else:
                    heapq.heappush(heap, (new_time, new_factor, nbr))
    return res

def solve():
    (n, m) = (int(i) for i in input().split())
    adj = [[] for i in range(n)]
    for _ in range(m):
        (u, v, w) = (int(i) for i in input().split())
        adj[u - 1].append((v - 1, w))
        adj[v - 1].append((u - 1, w))
    s = [int(i) for i in input().split()]
    print(bfs(adj, s))

def solve_t_times():
    for _ in range(int(input())):
        solve()
if __name__ == '__main__':
    solve_t_times()

Solution (Python):
from heapq import heappush, heappop

def solve():
    (n, m) = map(int, input().split())
    dct = [[] for i in range(n)]
    for i in range(m):
        (a, b, w) = map(int, input().split())
        dct[a - 1].append([b - 1, w])
        dct[b - 1].append([a - 1, w])
    A = list(map(int, input().split()))
    h = [[0, 0, A[0]]]
    mp = {}
    while h:
        (t, p, c) = heappop(h)
        if p == n - 1:
            print(t)
            return
        if c > A[p]:
            c = A[p]
        if p in mp and mp[p] <= c:
            continue
        else:
            mp[p] = c
        for (y, w) in dct[p]:
            heappush(h, [t + w * c, y, c])
for _ in range(int(input())):
    solve()

Solution (Python):
from heapq import heappush, heappop

def solve():
    (n, m) = map(int, input().split())
    dct = [[] for i in range(n)]
    for i in range(m):
        (a, b, w) = map(int, input().split())
        dct[a - 1].append([b - 1, w])
        dct[b - 1].append([a - 1, w])
    A = list(map(int, input().split()))
    h = [[0, 0, A[0]]]
    mp = {}
    while h:
        (t, p, c) = heappop(h)
        if p == n - 1:
            print(t)
            return
        if c > A[p]:
            c = A[p]
        if p in mp and mp[p] <= c:
            continue
        else:
            mp[p] = c
        for (y, w) in dct[p]:
            heappush(h, [t + w * c, y, c])
for _ in range(int(input())):
    solve()