[Programmers] ์ฌ ์ฐ๊ฒฐํ๊ธฐ
๋ฌธ์
๋ฌธ์ ์ค๋ช
Programmers - ์ฌ ์ฐ๊ฒฐํ๊ธฐ
n๊ฐ์ ์ฌ ์ฌ์ด์ ๋ค๋ฆฌ๋ฅผ ๊ฑด์คํ๋ ๋น์ฉ(costs)์ด ์ฃผ์ด์ง ๋, ์ต์์ ๋น์ฉ์ผ๋ก ๋ชจ๋ ์ฌ์ด ์๋ก ํตํ ๊ฐ๋ฅํ๋๋ก ๋ง๋ค ๋ ํ์ํ ์ต์ ๋น์ฉ์ return ํ๋๋ก solution์ ์์ฑํ์ธ์.
๋ค๋ฆฌ๋ฅผ ์ฌ๋ฌ ๋ฒ ๊ฑด๋๋๋ผ๋, ๋๋ฌํ ์๋ง ์์ผ๋ฉด ํตํ ๊ฐ๋ฅํ๋ค๊ณ ๋ด ๋๋ค. ์๋ฅผ ๋ค์ด A ์ฌ๊ณผ B ์ฌ ์ฌ์ด์ ๋ค๋ฆฌ๊ฐ ์๊ณ , B ์ฌ๊ณผ C ์ฌ ์ฌ์ด์ ๋ค๋ฆฌ๊ฐ ์์ผ๋ฉด A ์ฌ๊ณผ C ์ฌ์ ์๋ก ํตํ ๊ฐ๋ฅํฉ๋๋ค.
์ ๋ ฅ
n๊ฐ์ ์ฌ ์ฌ์ด์ ๋ค๋ฆฌ๋ฅผ ๊ฑด์คํ๋ ๋น์ฉ(costs)
n | costs |
---|---|
4 | [[0,1,1],[0,2,2],[1,2,5],[1,3,1],[2,3,8]] |
์ถ๋ ฅ
์ต์์ ๋น์ฉ์ผ๋ก ๋ชจ๋ ์ฌ์ด ์๋ก ํตํ ๊ฐ๋ฅํ๋๋ก ๋ง๋ค ๋ ํ์ํ ์ต์ ๋น์ฉ
์ ํ
- ์ฌ์ ๊ฐ์ n์ 1 ์ด์ 100 ์ดํ์ ๋๋ค.
- costs์ ๊ธธ์ด๋ ((n-1) * n) / 2์ดํ์ ๋๋ค.
- ์์์ i์ ๋ํด, costs[i][0] ์ costs[i] [1]์๋ ๋ค๋ฆฌ๊ฐ ์ฐ๊ฒฐ๋๋ ๋ ์ฌ์ ๋ฒํธ๊ฐ ๋ค์ด์๊ณ , costs[i] [2]์๋ ์ด ๋ ์ฌ์ ์ฐ๊ฒฐํ๋ ๋ค๋ฆฌ๋ฅผ ๊ฑด์คํ ๋ ๋๋ ๋น์ฉ์ ๋๋ค.
- ๊ฐ์ ์ฐ๊ฒฐ์ ๋ ๋ฒ ์ฃผ์ด์ง์ง ์์ต๋๋ค. ๋ํ ์์๊ฐ ๋ฐ๋๋๋ผ๋ ๊ฐ์ ์ฐ๊ฒฐ๋ก ๋ด ๋๋ค. ์ฆ 0๊ณผ 1 ์ฌ์ด๋ฅผ ์ฐ๊ฒฐํ๋ ๋น์ฉ์ด ์ฃผ์ด์ก์ ๋, 1๊ณผ 0์ ๋น์ฉ์ด ์ฃผ์ด์ง์ง ์์ต๋๋ค.
- ๋ชจ๋ ์ฌ ์ฌ์ด์ ๋ค๋ฆฌ ๊ฑด์ค ๋น์ฉ์ด ์ฃผ์ด์ง์ง ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ, ๋ ์ฌ ์ฌ์ด์ ๊ฑด์ค์ด ๋ถ๊ฐ๋ฅํ ๊ฒ์ผ๋ก ๋ด ๋๋ค.
- ์ฐ๊ฒฐํ ์ ์๋ ์ฌ์ ์ฃผ์ด์ง์ง ์์ต๋๋ค.
ํ์ด
ํด์ค
์ต์์ ์ฅํธ๋ฆฌ(MST) ์๊ณ ๋ฆฌ์ฆ ์ค ๊ฐ์ ์ ๊ฐ์ค์น๋ฅผ ๊ธฐ์ค์ผ๋ก ํ๋ ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ ํ์ด
๊ฐ์ ๊ฐ์ค์น๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฐ์ ์ ๋ณด๋ฅผ ์ค๋ฆ์ฐจ์ ์ ๋ ฌํ๋ค. ์ด ํ์ด์์๋ pq๋ฅผ ์ด์ฉํ๋ค.
pq.poll()๋ก ๊ฐ์ค์น๊ฐ ๊ฐ์ฅ ์์ ๊ฐ์ ์ ๋ฝ์ ๋ ์ ์ ์ด ๊ฐ์ ์งํฉ์ ํฌํจ๋๋์ง(์ ์ฅ ํธ๋ฆฌ์ ํฌํจ๋๋์ง, ์ฐ๊ฒฐ ๋๋์ง) ํ์ธํ ๋ค ์๋ก ๋ค๋ฅธ ์งํฉ์ ์๋ค๋ฉด union()ํ์ฌ ์ฐ๊ฒฐํ๋ค. ์ด๋ ๊ฐ์ค์น๋ฅผ ์ต์ข ๊ฐ์ค์น ์ถ๋ ฅ๊ฐ์ ํฉ์ฐํ๋ค.
์ฝ๋
import java.io.*;
import java.util.*;
/**
* [0223] PGS ํ์๋ฒ(Greedy) ์ฌ ์ฐ๊ฒฐํ๊ธฐ
* ๊ทธ๋ฆฌ๋, ํฌ๋ฃจ์ค์นผ, MST, Union-Find
*/
public class PGS_ํ์๋ฒ_์ฌ์ฐ๊ฒฐํ๊ธฐ {
public final int FROM = 0;
public final int TO = 1;
public final int COST = 2;
public int nodeCnt, edgeCnt;
public int[] roots;
// ๊ฐ์ค์น๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฐ์ ์ ๋ณด๋ฅผ ์ ์ฅ
public PriorityQueue<int[]> pq = new PriorityQueue<>((arr1, arr2) -> arr1[COST] - arr2[COST]);
// Union-Find ์๊ณ ๋ฆฌ์ฆ์ ์งํฉ ์์ฑ ๋ฉ์๋
public void makeSet() {
roots = new int[nodeCnt];
// ๋ฃจํธ์ ์๊ธฐ ์์ ์ ์ ์ฅํด๋
for (int i=0; i<nodeCnt; i++) roots[i] = i;
}
// Union-Find ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ ์งํฉ ๋ฃจํธ๋ฅผ ์ฐพ๋ ๋ฉ์๋
public int findRoot(int node) {
if (roots[node] == node) return node;
return roots[node] = findRoot(roots[node]);
}
// Union-Find ์๊ณ ๋ฆฌ์ฆ์ ๋ ์์๋ฅผ ๊ฐ์ ์งํฉ์ผ๋ก ๋ง๋๋ ๋ฉ์๋
public boolean union(int node1, int node2) {
int rootNode1 = findRoot(node1);
int rootNode2 = findRoot(node2);
// ๋ถ๋ชจ๊ฐ ๊ฐ์ผ๋ฉด ์ด๋ฏธ ๊ฐ์ ์งํฉ
if (rootNode1 == rootNode2) return false;
// ๋ถ๋ชจ๊ฐ ๋ค๋ฅด๋ฉด node2์ ๋ฃจํธ๋ฅผ node1์ ๋ฃจํธ๋ก ์ค์
roots[rootNode2] = rootNode1;
return true;
}
public int solution(int n, int[][] costs) {
nodeCnt = n;
edgeCnt = costs.length;
// pq๋ฅผ ์ด์ฉํด ๊ฐ์ค์น๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฐ์ ์ ๋ ฌ
sortDistances(costs);
// ๊ฐ์ค์น ํฉ์ด ์ต์๊ฐ ๋๋ ์ด ๊ฐ์ค์น ํฉ ๊ตฌํ๊ธฐ
int answer = getTotalCost();
return answer;
}
// pq์ ๊ฐ์ ์ ์ ๋ณด๋ฅผ ์ ์ฅ
public void sortDistances(int[][] costs) {
for (int i=0; i<edgeCnt; i++) pq.offer(costs[i]);
}
// ์ด ๊ฐ์ค์น ํฉ ์ต์๊ฐ ๋๋ ๊ฒฝ์ฐ ์ฐพ๊ธฐ
public int getTotalCost() {
int connected = 1;
int totalCost = 0;
// ์งํฉ ์์ฑํ ๋ค
makeSet();
// ๋ชจ๋ ์ ์ ์ฐ๊ฒฐ๋ ๋๊น์ง union
while(connected < nodeCnt) {
int[] costInfo = pq.poll();
// ์ถ๋ฐ ์ ์ ๊ณผ ๋์ฐฉ ์ ์ ์ด ์์ง ์ฐ๊ฒฐ ์๋์ผ๋ฉด ์ฐ๊ฒฐํ๊ณ ๊ฐ์ค์น ํฉ์ฐ
if (union(costInfo[FROM], costInfo[TO])) {
totalCost += costInfo[COST];
connected++;
}
}
return totalCost;
}
}
๐ก
- ์ค๋๋ง์ Union-Find ์๊ณ ๋ฆฌ์ฆ ๊ตฌํํจ! ์ญ์ Union-Find๋ ๊ฐ๋ ์ดํด๋ ์ฝ๊ณ ์ฌ๋ฐ๋ค ใ ใ
- ํฌ๋ฃจ์ค์นผ ์ง๊ถ ํ๋ฆผ๋ ๋ค์ ๋ด๋ณด์!