Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- sorting
- Math
- Method
- Number Theory
- array
- SQL
- java
- Matrix
- 자바
- 코딩테스트
- 코테
- 파이썬
- Tree
- simulation
- 구현
- greedy
- hash table
- Counting
- Binary Search
- Data Structure
- Binary Tree
- Class
- bit manipulation
- string
- dynamic programming
- two pointers
- implement
- database
- Stack
- geometry
Archives
- Today
- Total
코린이의 소소한 공부노트
Kruskal algorithm 본문
1. Problem
- 크루스칼 알고리즘을 사용하여 모든 노드를 연결하는 최소 비용을 구해보자.
- 최소 비용 신장 트리(minimum cost spanning tree)를 만드는 대표적인 알고리즘이다.
- 각 노드를 연결하는 간선의 정보(연결된 노드, 비용)를 이용해 간선을 정렬한 후 사이클을 만들지 않게 적은 비용의 간선부터 차례대로 선택해 나간다.
- 최소한의 비용으로 모든 노드를 이어야 하기 때문에, 사이클을 만드는 것은 비용 낭비가 된다.
- 간선을 선택하기 전에 사이클 테이블을 확인해야 하는데, 이는 이미 연결된 노드인지 알아보기 위함이다. 사이클 테이블은 union-find(합집합 찾기) 알고리즘을 이용한다.
2. Input
1) int[][] graph
- 연결된 노드를 표현
2) int[] cost
- cost[i] == graph[i]의 비용
3. Output
1) 모든 노드를 연결하는 최소 비용
4. Example
// 노드는 0번부터 6번까지 7개가 있고, 간선은 11개가 있다.
// 간선의 비용을 오름차순으로 정렬한다. [5,7,10,11,15,17,25,28,40,44,50]
// 사이클 테이블도 만들어 놓는다. parent = [0,1,2,3,4,5,6]
// 간선의 비용이 작은것부터 확인한다. 사이클 테이블을 보고 부모가 같지 않으면 해당 간선을 선택한다.
// 비용이 5인 간선: parent[2]==2 != parent[6]==6
-> MST= 2 - 6, cost = 5, parent = [0,1,2,3,4,5,2]
// 비용이 7인 간선: parent[3]==3 != parent[6]==2
-> MST= 2 - 6 - 3, cost = 12, parent = [0,1,2,2,4,5,2]
// 비용이 10인 간선: parent[0]==0 != parent[1]==1
-> MST= 0 - 1 / 2 - 6- 3, cost = 22, parent = [0,0,2,2,4,5,2]
// 비용이 11인 간선: parent[1]==0 != parent[5]==5
-> MST = 0 - 1 - 5 / 2 - 6- 3, cost = 33, parent = [0,0,2,2,4,0,2]
// 비용이 15인 간선: parent[3]==2 != parent[4]==4
-> MST = 0 - 1 - 5 / 2 - 6 - 3 - 4, cost = 48, parent = [0,0,2,2,2,0,2]
// 비용이 17인 간선: parent[0]==0 == parent[5]==0 -> skip
// 비용이 25인 간선: parent[1]==0 != parent[2]==2
-> MST = 0 - 1 - (5) - 2 - 6 - 3 - 4, cost = 73, parent = [0,0,0,0,0,0,0]
// 사이클 테이블의 값이 모두 같아졌으므로 종료한다.
// 모든 노드를 잇는 최소 비용은 73이다.
5. Code
static int[] parent = new int[7]; // 클래스 변수로 선언
// main()
// 7개의 노드와 11개의 간선에 대한 그래프를 2차원 배열로 표현
// graph[i][j]: i번과 j번을 연결하는 모든 간선들의 정보
// cost[i] == graph[i]의 비용
int[][] graph = {{2,6},{3,6},{0,1},{1,5},{3,4},{0,5},{1,2},{0,4},{1,4},{5,6},{2,3}};
int[] cost = {5,7,10,11,15,17,25,28,40,44,50}; // 편의상 오름차순으로 정렬시킴
for(int i=0 ; i<7 ; i++) // 각 노드에 대해 자기 값을 초기 부모로 지정한다
parent[i] = i;
int min = 0; // 최소 비용
for(int i=0 ; i<graph.length ; i++) { // 그래프의 간선을 따라가며 부모를 합친다.
if(!find(graph[i][0],graph[i][1])) { // 부모가 같지 않을 경우에만 선택해서
min += cost[i];
union(graph[i][0], graph[i][1]); // 합친다.
}
}
// 합치는 과정
static void union(int a, int b) {
a = getParent(a); // 두 노드의 부모를 찾은 후
b = getParent(b);
if(a<b) parent[b] = a; // 더 작은 수를 부모로 한다.
else parent[a] = b;
}
static int getParent(int a) { // 해당 노드의 부모를 찾아 반환한다.
if(parent[a]!=a) // 간선의 정보가 업데이트 될 때
parent[a] = getParent(parent[a]); // 부모가 달라질 수 있으므로
return parent[a]; // 재귀호출을 이용해 최종 부모를 찾는다.
}
static boolean find(int a, int b) { // 부모가 같으면 true를 반환한다.
return getParent(a)==getParent(b);
}
// main()
System.out.println(min); // 73
- 모든 간선을 다 돌게 해놨지만, 모든 노드를 방문했을 때 또는 parent의 값이 모두 같아지게 됐을 때 등의 break 조건을 걸어둘 수도 있다.
'Back-End > Algorithm' 카테고리의 다른 글
Topology sort (0) | 2023.06.09 |
---|---|
소수(prime number) 판별 알고리즘 (0) | 2023.06.07 |
Union-find algorithm for graph (0) | 2023.05.31 |
Depth First Search (0) | 2023.05.31 |
Breadth First Search (0) | 2023.05.30 |