본문 바로가기
Algorithm/Python

백준 2325번 개코 전쟁

by Shark_상어 2023. 3. 4.
728x90

“앙두레 강”이 개미와 코끼리 결혼식에서 기차를 아름답게 만드는 것을 실패했기 때문에 식장이 아수라장이 되고 결혼이 물거품이 되어버렸다. 급기야는 왕국 간에 분쟁으로 이어져 개미왕국은 코끼리왕국을 공격하기로 결정하였다. 동물나라 지도에서 개미왕국은 1번 정점에 위치해 있고 코끼리왕국은 N번 정점에 위치해 있다. 따라서 개미왕국이 1번 정점에서 N번 정점으로 공격을 하러 가는 상황이다. (개미왕국은 최단거리로 이동을 하게 되고, 코끼리왕국은 움직이지 않는다)

“개미”와 “코끼리”의 앞 글자를 따서 이 전쟁은 “개코전쟁”으로 역사에 기억된다.

“앙두레 강”은 자신 때문에 발생한 이 전쟁을 어떻게든 막으려고 한다. 협상을 할 시간을 벌기 위해 개미왕국이 코끼리왕국에 도착하는 시간을 최대한 늦추려고 한다. 그래서 “앙두레 강”은 사자왕국의 도움을 빌어 도로 중 딱 하나를 파괴하려고 하는데 어느 도로를 파괴해야 개미왕국이 최단거리로 가더라도 그 거리를 최대로 할 수 있을까?

“앙두레 강”를 도와 1번 정점에서 N번 정점으로의 최단거리가 최대가 되도록 도로 하나를 파괴하도록 하자. (어떤 하나의 도로를 파괴하더라도 1번 정점에서 N번 정점으로 도달 가능하다)

입력

첫 줄에 N과 M이 입력된다. N은 정점의 개수이고 M은 도로의 수이다. (1 ≤ N ≤ 1000, 1 ≤ M ≤ N×(N-1)/2)

다음 줄부터 M개의 줄에 도로의 정보가 입력된다.

i+1번째 줄에는 i번째 도로의 정보 xi yi zi가 입력되고 이 도로는 정점 xi와 정점 yi를 잇는 도로이며 지나는데 zi만큼의 시간이 걸린다는 것을 의미한다. 두 정점사이에는 두 개 이상의 길이 존재하지 않고 모든 도로는 양방향이며 한 도로를 파괴하는 것은 양방향의 길 모두를 파괴하는 것이다. (1 ≤ xi, yi ≤ N, 1 ≤ zi ≤ 1000)

출력

적당한 도로하나를 파괴했을 때 1번 정점에서 N번 정점으로의 최단거리의 최댓값을 출력한다.

 

2. 코드

import sys
from heapq import heappop, heappush

INF = sys.maxsize
input = sys.stdin.readline

def dijstra(start):
    dis = [INF] * (n + 1)
    dis[start] = 0
    parent[start] = [start]
    queue = []
    heappush(queue, (0, start))

    while queue:
        dist, now = heappop(queue)

        if dis[now] < dist:
            continue

        for i in maps[now]:
            cost = dist + i[1]

            if cost < dis[i[0]]:
                parent[i[0]] = parent[now] + [i[0]]
                dis[i[0]] = cost
                heappush(queue, (cost, i[0]))
    return parent
def dijstra2(s, e):
    dis = [INF] * (n + 1)
    dis[1] = 0

    queue = []
    heappush(queue, (0, 1))

    while queue:
        dist, now = heappop(queue)

        if dis[now] < dist:
            continue
        for i in maps[now]:
            if now == s and i[0] == e:
                continue
            elif now == e and i[0] == now:
                continue
            cost = dist + i[1]

            if cost < dis[i[0]]:
                dis[i[0]] = cost
                heappush(queue, (cost, i[0]))
    return dis
n, m = map(int, input().split())
maps = [[] for _ in range(n + 1)]
parent = [[] for _ in range(n + 1)]
for _ in range(m):
    a, b, c = map(int, input().split())
    maps[a].append((b, c))
    maps[b].append((a, c))

k = dijstra(1)
ans = 0
for i in range(len(k[n]) - 1):
    ans = max(ans, dijstra2(k[n][i], k[n][i + 1])[n])
print(ans)

 

3. 문제 접근

1. 브루트 포스(모든 다리를 하나씩 파괴하여 측정된 거리의 최솟값들중 최댓값 찾기)

-> M = N * (N - 1) / 2 즉 시간 복잡도 O(N^2) 이므로 시간 초과난다.

2.모든 다리를 파괴하진 못한다. 그럼 어느 다리를 파괴 해야 하는것인지 결정 해야한다.

3. 개미 왕국에서 시작해서 코끼리 왕국에 최소 비용으로 도착 하였을 때 들렸던 다리들을 파괴하여 다익스트라를 돌리면 된다. 

 

4. 보통은 [next_node] = current_node 이러한 형식으로 저장한다.

하지만 필자는 이중 배열를 이용하여 parent[next_node] = parent[current_node] + [next_node] 이런식으로 저장했다.

 

5.  그럼 n번째 배열에 개미 왕국에서 코끼리 왕국을 최소 비용으로 도착 하였을때 들렸던 노드들이 저장 되어 있다.

6. 이 노드들을 활용하여 다익스트라를 돌린다. 이때 next_node 나 current_node 에 가는 곳이 파괴해야할 노드들이 아니면 다익스트라를 진행하면 된다.

 

728x90

'Algorithm > Python' 카테고리의 다른 글

백준 5551번 쇼핑몰  (0) 2023.03.06
백준 5719번 거의 최단 경로  (0) 2023.03.05
백준 17270번 연예인은 힘들어  (0) 2023.03.04
프로그래머스 성격 유형 검사  (1) 2023.03.03
프로그래머스 호텔 대실  (0) 2023.03.01