코딩테스트 파이썬/그래프
신장트리
백엔드 개발자
2021. 10. 19. 12:54
신장트리: 하나의 그래프가 있을 때 모든 노드를 포함하면서 사이클이 존재하지 않는 부분 그래프
-> 연결그래프의 부분그래프
크루스칼 알고리즘: 최소신장 트리 (최소한의 비용으로 만들 수 있는 신장트리 찾는 알고리즘)의 대표 알고리즘
크루스칼은 가장 적은 비용으로 모든 노드를 연결할 수 있음. 그리디로 분류된다.
모든간선에 대해서 정렬을 수행후 가장 거리가 짧은 간선부터 집합에 포함시킨다.
사이클을 발생시킬 수 있는 간선은 집합에 포함하지 않는다.
알고리즘:
1.간선 데이터를 비용에 따라 오름차순으로 정렬
2. 간선을 하나씩 확인하며 현재의 간선이 사이클을 발생시키는지 확인.
-1 사이클이 발생하지 않으면 최소신장트리에 포함.
-2 사이클 발생 시 포함안함
3. 모든 간선에 대해서 2번 반복
노드가 N개면 최종적으로 최소신장트리에 포함되는 간선의 개수는 N-1개이다.
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
#노드, 간선개수입력 받기.
v,e=map(int,input().split())
parent=[0]*(v+1)
#모든 간선 리스트, 최종비용을 담을 변수
edges=[]
result=0
#부모테이블 자신으로 초기화
for i in range(1,v+1):
parent[i]=i
for i in range(e):
a,b,cost=map(int,input().split())
#비용순으로 정렬하기 위해 튜플의 첫번째 원소를 비용으로 지정
edges.append((cost,a,b))
#간선을 비용순으로 정렬
edges.sort()
#간선 하나씩 확인
for cost,a,b in edges:
#사이클을 확인해서 안생기면union 생기면
if find_parent(parent,a)!=find_parent(parent,b):
union_parent(parent,a,b)
#비용 더하기
result+=cost
print(result)
시간복잡도: 간선이 E개일 때 O(ElogE).
간선을 정렬하는 작업이 가장 오래걸리는 부분. E개의 데이터를 정렬하는데 걸리는 시간은O(logE)이다.