18223번: 민준이와 마산 그리고 건우
입력의 첫 번째 줄에 정점의 개수 V와 간선의 개수 E, 그리고 건우가 위치한 정점 P가 주어진다. (2 ≤ V ≤ 5,000, 1 ≤ E ≤ 10,000, 1 ≤ P ≤ V) 두 번째 줄부터 E개의 줄에 걸쳐 각 간선의 정보
www.acmicpc.net
문제
종강을 맞은 민준이는 고향인 마산으로 내려갈 계획을 짜고 있었다. 늘 그랬듯, 마산으로 갈 버스를 예약하려던 순간 민준이는 집으로 가는 다른 방법이 떠올랐다. 그것은 직접 지도를 보고 고향으로 가는 가장 짧은 길을 찾는 것이다.
그때, 먼저 고향으로 내려갔던 친구인 건우에게 연락이 왔다. 건우는 고향으로 내려가던 중 알 수 없는 일에 휘말려 외딴곳에 혼자 남겨지게 되었다. 건우는 유일한 구세주인 민준이에게 도움을 청한 것이었다. 그러나 마산의 남자인 민준이에게는 마산이 먼저였다. 민준이는 처량한 건우를 무시한 채 고향으로 떠나려고 했지만, 만약 고향으로 가는 길에 건우가 있다면 겸사겸사 도움을 줄 수 있을 것 같았다.
지도는 양방향 그래프 형태로 되어있다. 출발지는 1번 정점 마산은 V번 정점이다. 정점은 1~V까지 있다. 건우는 P번 정점에 있다.
그리고 항상 1번 정점에서 P번과 V번 정점으로 갈 수 있는 경로가 존재한다.
중복되는 간선과 자기 자신을 가리키는 간선은 존재하지 않는다.
아래와 같은 그래프가 있을 때,

위의 경우는 최단 경로가 두 가지 있다.
1→3→4→5→6 또는 1→3→5→6 이다. 이것 중에서 건우가 있는 곳, 즉 4번 정점이 포함된 최단 경로가 있으므로 이 경우에는 민준이가 건우를 도울 수 있다.
민준이가 건우를 도와주는 경로의 길이가 최단 경로의 길이보다 길어지지 않는다면, 민준이는 반드시 건우를 도와주러 간다.
어쩌면 지킬 수도 있는 민준이의 우정을 위해 우리가 도와주자!
입력
입력의 첫 번째 줄에 정점의 개수 V와 간선의 개수 E, 그리고 건우가 위치한 정점 P가 주어진다. (2 ≤ V ≤ 5,000, 1 ≤ E ≤ 10,000, 1 ≤ P ≤ V)
두 번째 줄부터 E개의 줄에 걸쳐 각 간선의 정보 a,b,c가 공백으로 구분되어 주어진다. 이는 a번 정점과 b번 정점 사이의 거리가 c임을 의미한다. (1 ≤ a,b ≤ V, 1 ≤ c ≤ 10,000)
출력
민준이가 찾은 최단 경로 위에 건우가 있다면 "SAVE HIM" 을 아니면 "GOOD BYE" 를 출력한다.
코드
from heapq import heappop, heappush
v, e, p = map(int, input().split())
edges = [[] for _ in range(v+1)]
for _ in range(e):
a, b, c = map(int, input().split())
edges[a].append((b, c))
edges[b].append((a, c))
def dijkstra(s, e):
q = [(0, s)]
dist = [int(1e9)]*(v+1)
dist[s] = 0
while q:
nd, nn = heappop(q)
for next, cost in edges[nn]:
if nd+cost < dist[next]:
heappush(q, (nd+cost, next))
dist[next] = nd+cost
return dist[e]
if dijkstra(1, p)+dijkstra(p, v) <= dijkstra(1, v):
print("SAVE HIM")
else:
print("GOOD BYE")
출발(1)→건우(P)→도착(V) 최단 거리 ≤ 출발(1)→도착(V) 최단 거리
이 경우가 존재한다면 민준이는 건우를 구해올 수 있고, 그렇지 않다면 구할 수 없다.
그렇기 때문에 다익스트라 알고리즘을 이용하여 구하려는 각 구간의 최단 거리를 구할 것이다.
다익스트라는 한 정점에서 다른 모든 정점까지의 최단 거리를 구하는 알고리즘이므로 구간별로 나눠서 구해야 한다.
다익스트라
- 우선순위 큐 q에 (거리, 출발 노드)를 넣는다.
- 출발노드에서부터 다른 모든 노드까지의 최단 거리를 저장할 배열 dist를 만든다. 출발점 s의 dist 값은 0이다.
- q가 빌 때까지 아래의 과정을 반복한다
- 우선순위 큐 q의 가장 앞에 있는 원소를 pop하여 원소의 값을 각각 nd, nn에 저장한다. nn은 노드, nd는 출발점 s로부터 nn까지의 거리이다.
- nn에서 갈 수 있는 다음 노드들 중 nn을 거쳐서 next로 가는 거리 nd+cost가 dist[next]의 값보다 작다면 dist[next]를 nd+cost로 갱신해주고 q에 (nd+cost, next)를 heappush한다.
이렇게 만든 다익스트라 함수를 이용하여 1→P, P->V, 1 →V 각각의 거리를 구하여 답을 찾는다.
'문제풀이 > 최단경로' 카테고리의 다른 글
[Python/파이썬] 백준 2458번 키 순서 (0) | 2024.04.12 |
---|---|
[Python/파이썬] 백준 20007번 떡 돌리기 (0) | 2024.04.11 |
[Python/파이썬] 백준 1058번 친구 (0) | 2024.01.22 |
[Python/파이썬] 백준 4485번 녹색 옷 입은 애가 젤다지? (0) | 2024.01.04 |
[Python/파이썬] 백준 14284번 간선 이어가기 2 (0) | 2023.12.29 |
18223번: 민준이와 마산 그리고 건우
입력의 첫 번째 줄에 정점의 개수 V와 간선의 개수 E, 그리고 건우가 위치한 정점 P가 주어진다. (2 ≤ V ≤ 5,000, 1 ≤ E ≤ 10,000, 1 ≤ P ≤ V) 두 번째 줄부터 E개의 줄에 걸쳐 각 간선의 정보
www.acmicpc.net
문제
종강을 맞은 민준이는 고향인 마산으로 내려갈 계획을 짜고 있었다. 늘 그랬듯, 마산으로 갈 버스를 예약하려던 순간 민준이는 집으로 가는 다른 방법이 떠올랐다. 그것은 직접 지도를 보고 고향으로 가는 가장 짧은 길을 찾는 것이다.
그때, 먼저 고향으로 내려갔던 친구인 건우에게 연락이 왔다. 건우는 고향으로 내려가던 중 알 수 없는 일에 휘말려 외딴곳에 혼자 남겨지게 되었다. 건우는 유일한 구세주인 민준이에게 도움을 청한 것이었다. 그러나 마산의 남자인 민준이에게는 마산이 먼저였다. 민준이는 처량한 건우를 무시한 채 고향으로 떠나려고 했지만, 만약 고향으로 가는 길에 건우가 있다면 겸사겸사 도움을 줄 수 있을 것 같았다.
지도는 양방향 그래프 형태로 되어있다. 출발지는 1번 정점 마산은 V번 정점이다. 정점은 1~V까지 있다. 건우는 P번 정점에 있다.
그리고 항상 1번 정점에서 P번과 V번 정점으로 갈 수 있는 경로가 존재한다.
중복되는 간선과 자기 자신을 가리키는 간선은 존재하지 않는다.
아래와 같은 그래프가 있을 때,

위의 경우는 최단 경로가 두 가지 있다.
1→3→4→5→6 또는 1→3→5→6 이다. 이것 중에서 건우가 있는 곳, 즉 4번 정점이 포함된 최단 경로가 있으므로 이 경우에는 민준이가 건우를 도울 수 있다.
민준이가 건우를 도와주는 경로의 길이가 최단 경로의 길이보다 길어지지 않는다면, 민준이는 반드시 건우를 도와주러 간다.
어쩌면 지킬 수도 있는 민준이의 우정을 위해 우리가 도와주자!
입력
입력의 첫 번째 줄에 정점의 개수 V와 간선의 개수 E, 그리고 건우가 위치한 정점 P가 주어진다. (2 ≤ V ≤ 5,000, 1 ≤ E ≤ 10,000, 1 ≤ P ≤ V)
두 번째 줄부터 E개의 줄에 걸쳐 각 간선의 정보 a,b,c가 공백으로 구분되어 주어진다. 이는 a번 정점과 b번 정점 사이의 거리가 c임을 의미한다. (1 ≤ a,b ≤ V, 1 ≤ c ≤ 10,000)
출력
민준이가 찾은 최단 경로 위에 건우가 있다면 "SAVE HIM" 을 아니면 "GOOD BYE" 를 출력한다.
코드
from heapq import heappop, heappush v, e, p = map(int, input().split()) edges = [[] for _ in range(v+1)] for _ in range(e): a, b, c = map(int, input().split()) edges[a].append((b, c)) edges[b].append((a, c)) def dijkstra(s, e): q = [(0, s)] dist = [int(1e9)]*(v+1) dist[s] = 0 while q: nd, nn = heappop(q) for next, cost in edges[nn]: if nd+cost < dist[next]: heappush(q, (nd+cost, next)) dist[next] = nd+cost return dist[e] if dijkstra(1, p)+dijkstra(p, v) <= dijkstra(1, v): print("SAVE HIM") else: print("GOOD BYE")
출발(1)→건우(P)→도착(V) 최단 거리 ≤ 출발(1)→도착(V) 최단 거리
이 경우가 존재한다면 민준이는 건우를 구해올 수 있고, 그렇지 않다면 구할 수 없다.
그렇기 때문에 다익스트라 알고리즘을 이용하여 구하려는 각 구간의 최단 거리를 구할 것이다.
다익스트라는 한 정점에서 다른 모든 정점까지의 최단 거리를 구하는 알고리즘이므로 구간별로 나눠서 구해야 한다.
다익스트라
- 우선순위 큐 q에 (거리, 출발 노드)를 넣는다.
- 출발노드에서부터 다른 모든 노드까지의 최단 거리를 저장할 배열 dist를 만든다. 출발점 s의 dist 값은 0이다.
- q가 빌 때까지 아래의 과정을 반복한다
- 우선순위 큐 q의 가장 앞에 있는 원소를 pop하여 원소의 값을 각각 nd, nn에 저장한다. nn은 노드, nd는 출발점 s로부터 nn까지의 거리이다.
- nn에서 갈 수 있는 다음 노드들 중 nn을 거쳐서 next로 가는 거리 nd+cost가 dist[next]의 값보다 작다면 dist[next]를 nd+cost로 갱신해주고 q에 (nd+cost, next)를 heappush한다.
이렇게 만든 다익스트라 함수를 이용하여 1→P, P->V, 1 →V 각각의 거리를 구하여 답을 찾는다.
'문제풀이 > 최단경로' 카테고리의 다른 글
[Python/파이썬] 백준 2458번 키 순서 (0) | 2024.04.12 |
---|---|
[Python/파이썬] 백준 20007번 떡 돌리기 (0) | 2024.04.11 |
[Python/파이썬] 백준 1058번 친구 (0) | 2024.01.22 |
[Python/파이썬] 백준 4485번 녹색 옷 입은 애가 젤다지? (0) | 2024.01.04 |
[Python/파이썬] 백준 14284번 간선 이어가기 2 (0) | 2023.12.29 |