오늘 배울 내용
Prim 알고리즘(욕심쟁이 알고리즘)
Kruskal 알고리즘(욕심쟁이 알고리즘)
상호 배타적 집합의 처리
Dijkstra Algorithm과 차이점
프림 알고리즘은 트리에 하나의 점 (선분)을 추가시킬 때 현재 상태의 트리에서 가장 가까운 점을 추가시킨다.
그러나 다익스트라의 알고리즘은 출발점으로부터 최단 거리가 확정되지 않은 점들 중에서 출발점으로부터 가장 가까운 점을 추가하고, 그 점의 최단 거리를 확정한다.
Pseudo code
// 임의의 정점 s를 선택한다(s로부터 트리를 키워나갈 것 - 에지를 T에 하나씩 추가)
S = {s} // 초기의 트리 T의 정점들의 집합
A = ø // 초기의 트리 T의 에지들의 집합
parents[s] = -1 // 초기화
while (A의 에지수 ≠ n-1)
S와 V-S 사이의 최소 가중치의 에지 e = (u, v)를 선택한다.
S = S U {u}
parent[v] = u
A = A U {e} // 트리 T에 e를 추가한다.
V-S에 속하는 정점 v에 대하여,
minWeight[v] : v와 S의 정점들 사이의 에지들의 최소 가중치
수행시간 : O(N^2)
// V의 각 정점 u에 대하여,
minWeight[u] = ∞
parent[u] = -1
// 임의의 정점 s를 선택한다.
S = {s} // 트리 T의 정점들의 집합
A = ø // 트리 T의 에지들의 집합
// s와 인접한 각 정점 v에 대하여,
minWeight[v] = 에지 (s, v)의 가중치
parent[v] = s
while (A의 에지 수 ≠ n-1)
// S와 V-S 사이의 최소 가중치의 에지 e = (u, v)를 선택한다.
// -> V-S의 정점들의 minWeight[]가 최소인 정점을 선택 (S에 이미 있는 정점은 제외)
S = S U {u}
Parent[v] = u
A = A U {e} // T에 e를 추가한다.
// V-S의 정점들의 minWeight[]를 update
node = adjList[v]
while node is not None:
// v와 인접한 V-S의 정점 w에 대하여,
w = node.vertex
if (weight(v, w) < minWeight([w])
minWeight[w] = weight(v, w)
parent[w] = v
node = node.link
V-S에 속하는 정점 v에 대하여,
minWeight[v] : v와 S의 정점들 사이의 에지들의 최소 가중치
V-S의 모든 정점들의 minWeight[] 값을 최소힙 H로 관리
수행시간 : O(M * log N)
// V의 각 정점 v에 대하여,
minWeight[u] = ∞
parent[u] = -1
// 임의의 정점 s를 선택한다.
S = {s} // 트리 T의 정점들의 집합
A = ø // 트리 T의 에지들의 집합
// s와 인접한 각 정점 v에 대하여,
minWeight[v] = 에지 (s, v)의 가중치
parent[v] = s
// V-S의 모든 정점들과 그 minWeight 값을 힙 H에 삽입
while (A의 에지 수 ≠ n-1)
u = deleteMin(H) // 최소힙 H에서 minWeight가 최소인 정점 삭제
S = S U {u}
Parent[v] = u
A = A U {e} // T에 e를 추가한다.
// V-S의 정점들의 minWeight[]를 update
// u와 인접한 V-S의 정점 w에 대하여,
if (weight(u, v) < minWeight([v])
minWeight[v] = weight(u, v)
최소힙 H를 update
parent[v] = u
MST(최소 비용 신장 트리) 가
의 조건에 근거하여 각 단계에서 사이클을 이루지 않는 최소 비용 간선을 선택 한다
Kruskal’s algorithm은 최소 비용 신장 부분 트리를 찾는 알고리즘이다. 변의 개수를 E, 꼭짓점의 개수를 V라고 하면 이 알고리즘은 O(E*logE)의 시간복잡도를 가진다.
while (|F| != n-1)
R에서 최소 가중치의 에지(v, w)를 제거한다.
if ((v, w)를 F에 추가할 때, 사이클을 만들지 않으면),
(v, w)를 F에 추가한다.
if (v, w)를 F에 추가할 때, 사이클을 만들지 않으면
에 대한 판별은 어떻게?크루스칼 알고리즘
그래프의 간선들을 가중치의 오름차순으로 정렬한다.
정렬된 간선 리스트에서 순서대로 사이클을 형성하지 않는 간선을 선택한다.
즉, 가장 낮은 가중치를 먼저 선택한다.
사이클을 형성하는 간선을 제외한다.
해당 간선을 현재의 MST(최소 비용 신장 트리)의 집합에 추가한다.
O(E*logE)
가 된다.O(N^2)
이므로, {
p[x] <- x // 노드 x를 유일한 원소로하는 집합 생성
}
{
p[Find-Set(y)] <- Find-Set(x)
// 노드 x가 속한 집합과 노드 y가 속한 집합을 각각 알아낸 후 합친다.
}
{
if (x = p[x]) // 노드 x가 속한 집합을 알아낸다.
then return x // 노드 x가 속한 트리의 루트노드를 반환한다.
else return Find-Set(p[x])
}
Algorithm Make-Set(x)
p[x] <- x
rank[x] <- 0
Algorithm Union(x, y)
x' <- Find-Set(x)
y' <- Find-Set(y)
if (rank[x'] > rank[y'])
then p[y'] <- x'
else
p[x'] <- y'
if (rank[x'] = rank[y']) then rank[y'] <- rank[y'] + 1 (rank + 1)
Algorithm Find-Set(x)
if (p[x] ≠ x) then p[x] <- Find-Set(p[x])
return p[x]
O(M٭log*N)
이다.Kruskal 알고리즘
O(m*logm)
(ex 퀵정렬)O(m)
O(m*logm)