Solve 100 past questions that beginners and intermediates should solve in Python. The goal is to turn light blue by the time you finish solving everything.
This article is "056 --059 Shortest Path Problem: Dijkstra's Algorithm".
I understood the Dijkstra method and the Floyd-Warshall method by watching the channel of Abdul Bari on YouTube. It was very easy to understand, and I solved the problem after watching the video and understanding the algorithm, so I was able to proceed smoothly.
import heapq
#--------------------------------------[Input receipt]--------------------------------------#
INF = float('inf')
V, E, r = map(int, input().split())
graph = [[] for _ in range(V)]
for _ in range(E):
s, t, d = map(int, input().split())
graph[s].append((t, d))
#--------------------------------------[initial value]--------------------------------------#
dp = [INF] * V
visited = [-1] * V
dp[r] = 0
h = [(0, r)]
#--------------------------------------[Start exploration]--------------------------------------#
while h:
d, s = heapq.heappop(h) #Extract in ascending order of cost
if visited[s] == 1:
continue
visited[s] = 1
targets = graph[s]
for target in targets:
t, d = target
if dp[t] > dp[s] + d:
dp[t] = dp[s] + d
heapq.heappush(h, (dp[t], t))
#--------------------------------------[Answer]--------------------------------------#
for answer in dp:
if answer == INF:
print('INF')
else:
print(answer)
Fetch in the heap in ascending order. The algorithm is easy to understand 3.6 Dijkstra Algorithm --Single Source Shortest Path --Greedy Method. If you drop it in the code as explained in this video, it will be an answer.
import heapq
def cal_cost(graph, n, start, end):
#--------------------------------------[initial value]--------------------------------------#
dp = [INF] * (n + 1)
visited = [-1] * (n + 1)
dp[start] = 0
h = [(0, start)]
#--------------------------------------[Start exploration]--------------------------------------#
while h:
_, s = heapq.heappop(h) #s is start,e is end
if visited[s] == 1:
continue
visited[s] = 1
targets = graph[s]
for target in targets:
cost, e = target
if dp[e] > dp[s] + cost:
dp[e] = dp[s] + cost
heapq.heappush(h, (dp[e], e))
return dp[end]
if __name__ == "__main__":
INF = float('inf')
n, k = map(int, input().split()) #n is the number of islands, k is the number of lines for the following input
graph = [[] for _ in range(n+1)] #1 index
answer_list = []
for _ in range(k):
info_list = list(map(int, input().split()))
if info_list[0] == 1:
island_1, island_2, cost = info_list[1], info_list[2], info_list[3]
graph[island_1].append((cost, island_2))
graph[island_2].append((cost, island_1))
else:
start, end = info_list[1], info_list[2]
answer = cal_cost(graph, n, start, end)
answer_list.append(answer)
for answer in answer_list:
if answer == INF:
print(-1)
else:
print(answer)
It's a slightly different version of question 56, but basically it's the same thing.
In particular, the contents of `cal_cost ()`
are almost the same, so you can solve it by just receiving the input.
from collections import deque
import heapq
#--------------------------------------[initial value]--------------------------------------#
INF = float('inf')
N, M, K, S = map(int, input().split()) #N towns, M roads, K dominated by zombies, dangerous towns within S from zombies
P, Q = map(int, input().split()) #P yen if not dangerous, Q yen if dangerous
zombie_towns = [int(input()) for _ in range(K)]
graph = [[] for _ in range(N+1)]
for _ in range(M):
townA, townB = map(int, input().split())
graph[townA].append((INF, townB))
graph[townB].append((INF, townA))
#--------------------------------------[Explore the distance from Zombie Town with BFS]--------------------------------------#
# zombie_BFS to find dangerous towns within S from towns
visited = [INF] * (N+1)
q = deque()
for zombie_town in zombie_towns:
q.append(zombie_town)
visited[zombie_town] = 0
while q:
start_town = q.popleft()
for target in graph[start_town]:
_, end_town = target
if visited[end_town] != INF:
continue
q.append(end_town)
visited[end_town] = visited[start_town] + 1
# zombie_Record as a set for dangerous towns within S from towns
cost_Q = set()
for i in range(1, N+1):
if visited[i] <= S:
cost_Q.add(i)
#--------------------------------------[Search for the shortest distance with heapq]]--------------------------------------#
#Turn the heap
dp = [INF] * (N+1)
visited2 = [-1] * (N+1)
dp[1] = 0
h = [(0, 1)]
answer = 0
while h:
cost, s = heapq.heappop(h) #s is start,e is end
if visited2[s] == 1:
continue
if s in zombie_towns: #Don't go to towns with zombies
continue
visited2[s] = 1
targets = graph[s]
for target in targets:
_, e = target
if e in cost_Q: # zombie_Q for dangerous towns within S from towns,Other than that, P
cost = Q
else:
cost = P
if dp[e] > dp[s] + cost:
dp[e] = dp[s] + cost
heapq.heappush(h, (dp[e], e))
if e == N: #When the destination comes out, break there
answer = dp[s] #The answer is the cost recorded just before the destination
break
if answer != 0:
break
print(answer)
The implementation is heavy. However, if you break down what you are doing, it is easy to understand because it is a combination of problems that you have solved so far. The problems can be broadly divided into two: "find the distance from the zombie town" and "find the minimum cost path".
To "find the distance from the zombie town", use `BFS``` to find the shortest distance from the zombies. To "find the lowest cost path", use the Dijkstra method with
`heapq```.
from collections import deque
import heapq
#------------------[Find the distance from each point to each destination with BFS]----------------------#
def bfs(start, graph):
visited = [-1] * N
q = deque()
q.append(start)
visited[start] = 0
while q:
s = q.popleft()
targets = graph[s]
for e in targets:
if visited[e] != -1:
continue
visited[e] = visited[s] + 1
q.append(e)
return visited
if __name__ == "__main__":
#------------------[input]----------------------#
INF = float('inf')
N, K = map(int, input().split()) #N towns, K roads
costs = [INF] * N
counts = [0] * N
for i in range(N):
C, R = map(int, input().split())
costs[i] = C
counts[i] = R
graph = [[] for _ in range(N)]
for _ in range(K):
A, B = map(int, input().split())
A -= 1
B -= 1
graph[A].append(B)
graph[B].append(A)
#------------------[Rebuild graph]]----------------------#
graph2 = [[] for _ in range(N)]
for start in range(N):
end_list = bfs(start, graph)
for end, count in enumerate(end_list):
if counts[start] < count:
continue
if start == end:
continue
graph2[start].append((costs[start], end)) #Add to graph only the part that can go within the number of times limit
#------------------[Shortest distance with heapq]]----------------------#
dp = [INF] * N
visited = [-1] * N
dp[0] = 0
h = [(0, 0)]
while h:
_, s = heapq.heappop(h)
if visited[s] == 1:
continue
visited[s] = 1
targets = graph2[s]
for target in targets:
cost, e = target
if dp[e] > dp[s] + cost:
dp[e] = dp[s] + cost
heapq.heappush(h, (dp[e], e))
print(dp[N-1])
With the above code, 2 out of 5 cases will be `TLE```. If you submit with ``` pypy```, only one of the five cases will be
`MLE```.
The big idea is similar to question 58, doing `` `BFS``` and then Dijkstra's algorithm.
When you write a policy,
`graph``` with
`bfs```
`graph2``` with a
end_list
and a
`counts with the input value `` R
recorded. graph2
, all you have to do is Dijkstra's algorithm.is.
The graph
given in the problem statement is used for `bfs```, The reconstructed
`graph2``` is used in Dijkstra's algorithm,
Is that the interesting part of this problem?
Recommended Posts