크게 생각하고, 목표를 높게 잡고, 대담하게 행동하라.

“언젠가는 목표에 이를지도 모르는 단계를 밟는 것으로는 언제나 실패한다. 모든 단계가 그 자체로 목표인 동시에 목표로 이르는 단계여야한다.” - 괴테

알고리즘/Kruskal

[Python] 백준 2887 - 행성터널

o_onn5 2023. 1. 24. 13:36
728x90

https://www.acmicpc.net/problem/2887

 

2887번: 행성 터널

첫째 줄에 행성의 개수 N이 주어진다. (1 ≤ N ≤ 100,000) 다음 N개 줄에는 각 행성의 x, y, z좌표가 주어진다. 좌표는 -109보다 크거나 같고, 109보다 작거나 같은 정수이다. 한 위치에 행성이 두 개 이

www.acmicpc.net

 

크루스칼 문제다.

일반적인 크루스칼 개념을 적용시켜서 푸는 것은 동일하다.

각 노드의 x축 y축 z축 차이를 탐색한 뒤에 절댓값이 가장 작은 가중치를 선택하면 된다.

그렇다고 모든 노드를 하나씩 비교해보면 시간초과가 난다.

 

따라서 간선의 가중치와 노드를 저장한 뒤에 우선순위 정렬을 시행한 뒤 비교해줘야한다.

 

정리해보면

1. x축 y축 z축의 리스트를 하나 만든다.

2. 각  리스트에 x축, y축, z축 값을 노드번호와 함께 저장한다.

3. 각 리스트를 가중치 우선순위로 정렬시킨다.

4. 앞에서부터 2개씩 순차적으로 비교하며 해당 간선과 노드를  edges 리스트에 저장한다.

5. edges를 정렬시킨다.

6. 크루스칼 알고리즘을 진행한다.

def find_parent(parent, x):
    if parent[x] !=x:
        parent[x] = find_parent(parent, parent[x])
    return parent[x]

def union_parent(parent, a, b):
    a = find_parent(parent, a)
    b = find_parent(parent, b)
    if a<b:
        parent[b] = a
    else:
        parent[a] = b
    
n = int(input())

xs, ys, zs = [], [], []
# 간선의 가중치와 노드를 저장 후 정렬
for i in range(1,n+1):
    x,y,z = map(int,input().split())
    xs.append((x,i))
    ys.append((y,i))
    zs.append((z,i))
xs.sort()
ys.sort()
zs.sort()

parent = [i for i in range(n+1)]
result = 0

edges = []
# cost: xs[i][0]
# location: xs[i][1]
for i in range(n-1):
    edges.append((xs[i+1][0] - xs[i][0], xs[i][1],xs[i+1][1]))
    edges.append((ys[i+1][0] - ys[i][0], ys[i][1],ys[i+1][1]))
    edges.append((zs[i+1][0] - zs[i][0], zs[i][1],zs[i+1][1]))
edges.sort()

for edge in edges:
    cost, a, b = edge
    if find_parent(parent, a) != find_parent(parent, b):
        union_parent(parent, a, b)
        result+=cost
print(result)

 

728x90

'알고리즘 > Kruskal' 카테고리의 다른 글

[Python] 백준 4386 - 별자리 만들기  (0) 2023.01.27
[Python] 크루스칼 알고리즘 baseline  (0) 2023.01.24