CS/알고리즘_문제풀이(파이썬)

특정 최단거리

Jedy_Kim 2021. 8. 4. 14:43
728x90

문제

무방향 그래프가 주어질 때, 정점 1번에서 정점 N번으로 가는 최단거리를 구하려 하는데, 그 과정에서 두 개의 정점을 반드시 거쳐야 한다. 한 번 방문했던 정점을 또 다시 방문하는 것도 허용하고, 간선도 마찬가지로 여러번 방문하는 것을 허용한다고 할 때, 1번에서 N번으로 가는 “특정한" 최단거리를 출력하는 프로그램을 작성하시오.

 

입력

첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. ( 4 ≤ N ≤ 1,000, 1 ≤ M ≤ N*(N-1)/2 ) 둘째 줄부터 간선의 정보가 주어진다. 각 줄은 두 개의 숫자 a, b, c로 이루어져 있으며, 이는 정점 a와 정점 b가 가중치 c인 간선으로 연결되어 있다는 의미이다. 마지막 줄에는 반드시 거쳐야 하는 두 정점 A, B가 주어진다. ( 1 ≤ a, b ≤ N, 2 ≤ A, B ≤ N, 1 ≤ c ≤ 50,000, a ≠ b, A ≠ B )

 

출력

1번 정점에서 N번 정점으로 가는 “특정한" 최단거리를 출력한다. 단, “특정한" 최단거리란, 주어진 정점 A와 B를 반드시 방문할 때의 최단거리를 의미한다.

 

예제 입력

4 6

1 2 3

2 3 3

3 4 1

1 3 5

2 4 5

1 4 4

2 3

예제 출력

7

 

#코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
from collections import deque
import sys
 
def dijkstra(graph, start, shortest):
  global N, M
  
  deq = deque()
  deq.append((0, start))
  
  while deq:
    cand_shortest, now = deq.popleft()
    
    if cand_shortest > shortest[now]: continue
    
    for adj in graph[now]:
      cost = cand_shortest + adj[1]
      
      if cost < shortest[adj[0]]:
        shortest[adj[0]] = cost
        deq.append((cost, adj[0]))
      
 
if __name__ == "__main__":
  input = sys.stdin.readline
  INF   = int(1e9)
  
  N, M    = map(int, input().split())
  myGraph = [[] for _ in range(N + 1)]
  
  for _ in range(M):
    a, b, c = map(int, input().split())
    
    myGraph[a].append((b, c))
    myGraph[b].append((a, c))
  
  A, B = map(int, input().split())
  
  res_sum = 0
  # 1. 시작점부터 A, B 각각의 최단거리를 구한다.
  shortest = [INF for _ in range(N + 1)]
  dijkstra(myGraph, 1, shortest) 
  # 2. 더 작게 나온 결과를 첫 번째 방문지로 결정한다.
  # 더 작게 나온 최단거리부터 다음 거점까지 최단 거리를 구한다.
  min_val = 0
  if shortest[A] < shortest[B]: # 시작점 -> A -> B 
    min_val = shortest[A]
    shortest = [INF for _ in range(N + 1)]
    dijkstra(myGraph, A, shortest)
    res_sum += (min_val + shortest[B])
    # 3. 마지막 거점에서 목적지까지의 최단 거리를 구한다.
    shortest = [INF for _ in range(N + 1)]
    dijkstra(myGraph, B, shortest) 
    res_sum += shortest[N]
  else# 시작점  -> B -> A
    min_val = shortest[B]
    shortest = [INF for _ in range(N + 1)]
    dijkstra(myGraph, B, shortest)
    res_sum += (min_val + shortest[A])
    # 3. 마지막 거점에서 목적지까지의 최단 거리를 구한다.
    shortest = [INF for _ in range(N + 1)]
    dijkstra(myGraph, A, shortest) 
    res_sum += shortest[N]
  
  print(res_sum)
cs

 

# 코드 (개선)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from collections import deque
import sys
 
def dijkstra(graph, start, shortest):
  global N, M
  
  deq = deque()
  deq.append((0, start))
  
  while deq:
    cand_shortest, now = deq.popleft()
    
    if cand_shortest > shortest[now]: continue
    
    for adj in graph[now]:
      cost = cand_shortest + adj[1]
      
      if cost < shortest[adj[0]]:
        shortest[adj[0]] = cost
        deq.append((cost, adj[0]))
      
 
if __name__ == "__main__":
  input = sys.stdin.readline
  INF   = int(1e9)
  
  N, M    = map(int, input().split())
  myGraph = [[] for _ in range(N + 1)]
  
  for _ in range(M):
    a, b, c = map(int, input().split())
    
    myGraph[a].append((b, c))
    myGraph[b].append((a, c))
  
  A, B = map(int, input().split())
  
  res_a_sum = 0
  res_b_sum = 0
  # 1. 시작점부터 A, B 각각의 최단거리를 구한다.
  shortest_origin = [INF for _ in range(N + 1)]
  dijkstra(myGraph, 1, shortest_origin) 
  
  # 2. 더 작게 나온 결과를 첫 번째 방문지로 결정한다.
  #################################################################################
  min_val = 0
  min_val = shortest_origin[A]
  shortest = [INF for _ in range(N + 1)]
  dijkstra(myGraph, A, shortest)
  res_a_sum += (min_val + shortest[B])
  # 3. 마지막 거점에서 목적지까지의 최단 거리를 구한다.
  shortest = [INF for _ in range(N + 1)]
  dijkstra(myGraph, B, shortest) 
  res_a_sum += shortest[N]
  #################################################################################
  min_val = 0
  min_val = shortest_origin[B]
  shortest = [INF for _ in range(N + 1)]
  dijkstra(myGraph, B, shortest)
  res_b_sum += (min_val + shortest[A])
  # 3. 마지막 거점에서 목적지까지의 최단 거리를 구한다.
  shortest = [INF for _ in range(N + 1)]
  dijkstra(myGraph, A, shortest) 
  res_b_sum += shortest[N]
  #################################################################################
  print(min(res_a_sum, res_b_sum))
cs

 

반응형

'CS > 알고리즘_문제풀이(파이썬)' 카테고리의 다른 글

2020 KAKAO BLIND RECRUITMENT - 자물쇠와 열쇠  (0) 2021.08.06
파티  (0) 2021.08.04
Level 3. 전염병  (0) 2021.08.03
배상 비용 최소화 사본  (0) 2021.08.02
게임아이템  (0) 2021.08.02