KEEP GOING
[python code review] 7주차 (최단경로, 궁금한 민호, 웜홀) 본문
https://www.acmicpc.net/problem/1753
1753번: 최단경로
첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가
www.acmicpc.net
import heapq
V, E = map(int, input().split())
k = int(input())
graph = [[] for _ in range(V+1)]
distance = [1e9 for _ in range(V+1)]
for _ in range(E):
u, v, w = map(int, input().split())
graph[u].append((w, v))
def dijkstra(start):
distance[start] = 0
queue = []
heapq.heappush(queue, [0, start])
while queue:
cost, now = heapq.heappop(queue)
if distance[now] < cost:
continue
for next_cost, next_node in graph[now]:
weight = next_cost + cost
if weight < distance[next_node]:
distance[next_node] = weight
heapq.heappush(queue, [weight, next_node])
for i in range(1, V+1):
if distance[i] == 1e9:
print('INF')
else:
print(distance[i])
dijkstra(k)
heapq로 푸는 접근 방법은 떠올랐는데
start부터 각 노드까지의 최소 비용을 distance 배열로 저장하는 방법을 까먹었다 (;;)
참고하기 좋은 블로그 https://ujin-dev.tistory.com/35
https://www.acmicpc.net/problem/1507
1507번: 궁금한 민호
첫째 줄에 도시의 개수 N(1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에 각각의 도시 사이에 이동하는데 필요한 시간이 주어진다. A에서 B로 가는 시간과 B에서 A로 가는 시간은 같다. 또, A와 B
www.acmicpc.net
n = int(input())
graph = [[0]*(n+1)]
deactivated = [[False]*(n+1) for _ in range(n+1)]
for i in range(n):
graph.append([0] + list(map(int, input().split())))
# 거쳐가는 점
for k in range(1, n+1):
# 시작점
for a in range(1, n+1):
# 끝점
for b in range(1, n+1):
if a == b or a == k or b == k:
continue
if graph[a][b] == graph[a][k] + graph[k][b]:
deactivated[a][b] = True
elif graph[a][b] > graph[a][k] + graph[k][b]:
print(-1)
exit()
total = 0
for a in range(1, n+1):
for b in range(a, n+1):
if not deactivated[a][b]:
total += graph[a][b]
print(total)
플로이드 워셜 알고리즘을 이용하여 접근하면 된다.
플로이드 워셜 알고리즘 -> https://www.youtube.com/watch?v=hw-SvAR3Zqg
플로이드 워셜 알고리즘은 임의의 노드 k를 이용해 a부터 b까지의 최단 경로를 구하는 방법을 제공한다.
이 점화식은 다음과 같다.
Dab = min(Dab, Dak + Dkb) -- > Dab: a부터 b까지의 거리
만약에 Dab와 Dak+Dkb가 같다면 이는 a와 b는 간접 경로를 통해 이동할 수 있다는 뜻이다. 따라서 a와 b를 연결짓는 간선은 제거해줄 수 있다. 간선 제거를 위해 사용되는 배열이 deactivated이다.
그리고 Dab가 Dak+Dkb보다 크다면 이는 Dab는 a부터 b까지의 최단 경로라는 조건에 어긋난다.
따라서 이러한 경우에는 -1을 출력해준다.
https://www.acmicpc.net/problem/1865
1865번: 웜홀
첫 번째 줄에는 테스트케이스의 개수 TC(1 ≤ TC ≤ 5)가 주어진다. 그리고 두 번째 줄부터 TC개의 테스트케이스가 차례로 주어지는데 각 테스트케이스의 첫 번째 줄에는 지점의 수 N(1 ≤ N ≤ 500),
www.acmicpc.net
def bellman(start):
distance[start] = 0
for i in range(1, n+1):
for j in range(1, n+1):
for nxt, time in graph[j]:
# 현재 노드를 거쳐서 이동하는 경우가 더 짧을 경우
if distance[nxt] > distance[j] + time:
distance[nxt] = distance[j] + time
# n번 이후에도 값이 갱신되면 음수 사이클 존재
if i == n:
return True
return False
for _ in range(1, int(input())+1):
n, m, w = map(int, input().split())
graph = [[] for _ in range(n+1)]
distance = [1e9 for _ in range(n + 1)]
for _ in range(m):
s, e, t = map(int, input().split())
graph[s].append([e, t])
graph[e].append([s, t])
for _ in range(w):
s, e, t = map(int, input().split())
graph[s].append([e, -t])
negative_cycle = bellman(1)
if not negative_cycle:
print("NO")
else:
print("YES")
벨만 포드 알고리즘을 이용하는 전형적인 문제이다.
유사 문제 -> 백준 타임머신 https://www.acmicpc.net/problem/11657
11657번: 타임머신
첫째 줄에 도시의 개수 N (1 ≤ N ≤ 500), 버스 노선의 개수 M (1 ≤ M ≤ 6,000)이 주어진다. 둘째 줄부터 M개의 줄에는 버스 노선의 정보 A, B, C (1 ≤ A, B ≤ N, -10,000 ≤ C ≤ 10,000)가 주어진다.
www.acmicpc.net
벨만포드 알고리즘 개념 -> https://www.youtube.com/watch?v=Ppimbaxm8d8
'code review > study' 카테고리의 다른 글
[python code review] 8주차(여행가자, 문제집, 최소 스패닝 트리) (0) | 2022.04.04 |
---|---|
[python code review] 8주차(병든 나이트, 친구비, 퍼즐) (0) | 2022.03.29 |
[python code review] 7주차 (소용돌이 예쁘게 출력하기, N-Queen, 나무 자르기) (0) | 2022.03.18 |
[python code review] 6주차 (파일 합치기, 정수 삼각형, 가장 큰 정사각형) (0) | 2022.03.15 |
[python code review] 6주차 (암호 만들기, 기둥과 보 설치, Z) (0) | 2022.03.11 |