사용자 도구

사이트 도구


ps:problems:boj:1774

우주신과의 교감

ps
링크acmicpc.net/…
출처BOJ
문제 번호1774
문제명우주신과의 교감
레벨골드 4
분류

최소 신장 트리

시간복잡도O(n^2)
인풋사이즈n<=1000
사용한 언어Python
제출기록32952KB / 388ms
최고기록388ms
해결날짜2022/10/04
태그

30단계

풀이

  • 유클리디안 최소 신장 트리 (Minimum Spanning Tree / MST)의 변형. 유클리디안 최소 신장 트리는, 들로네 삼각분할을 이용한 고급 알고리즘을 사용하지 않는 범위에서는, 그냥 완전 그래프를 만들고서 거기에서 MST를 찾는 방식으로 구하게 된다 (별자리 만들기 참고). 여기에서는 이때 미리 주어진 엣지들을 먼저 포함 시킨다음에 이어서 MST를 찾도록 알고리즘을 살짝 바꾸면 된다.
  • 크루스칼 알고리즘을 쓸 경우는 간단하게 바꿀수 있다. 먼저 미리 주어진 엣지들을 union 해놓고서, 나머지 엣지들을 대상으로 알고리즘을 계속 돌리면 된다. 프림으로 할 경우에는 mst에 포함된 노드들을 하나 추가할때마다, 그 노드들과 미리 연결되어있던 노드들을 찾아서 함께 추가하는 식으로 고쳐야 한다.
  • 하지만 더 간단하게, 그냥 기존 알고리즘 코드를 그냥 그대로 쓸 수 있는 방법도 있다. 미리 연결된 점들을 가중치를 0인 엣지로 취급해서 원래 그래프에 추가해주고 그대로 돌리면 된다. 이렇게 그래프를 만들면 프림이나 크루스칼이나 모두 원하는대로 동작한다. 완전그래프라서 O(n^2)의 프림 알고리즘이 O(n^2logn)의 크루스칼 알고리즘보다 빠르게 동작한다

코드

"""Solution code for "BOJ 1774. 우주신과의 교감".

- Problem link: https://www.acmicpc.net/problem/1774
- Solution link: http://www.teferi.net/ps/problems/boj/1774

Tags: [Minimum spanning tree]
"""

import math
import sys
from teflib import graph as tgraph


def main():
    N, M = [int(x) for x in sys.stdin.readline().split()]
    coords = [[int(x) for x in sys.stdin.readline().split()] for _ in range(N)]
    edges = set()
    for _ in range(M):
        u, v = [int(x) for x in sys.stdin.readline().split()]
        edges.add((u - 1, v - 1))
        edges.add((v - 1, u - 1))

    mat_graph = tgraph.create_mat_graph(
        N, lambda u, v: (0 if
                         (u, v) in edges else math.dist(coords[u], coords[v])))
    mst_edges = tgraph.minimum_spanning_tree_dense(mat_graph)
    answer = sum(w for u, v, w in mst_edges)
    print(f'{answer:.2f}')


if __name__ == '__main__':
    main()

토론

댓글을 입력하세요:
W C B W᠎ B
 
ps/problems/boj/1774.txt · 마지막으로 수정됨: 2022/10/07 17:38 저자 teferi