π νλ‘κ·Έλλ¨Έμ€ / Level3 / μ¬ μ°κ²°νκΈ°
π λ¬Έμ
νλ‘κ·Έλλ¨Έμ€
μ½λ μ€μ¬μ κ°λ°μ μ±μ©. μ€ν κΈ°λ°μ ν¬μ§μ λ§€μΉ. νλ‘κ·Έλλ¨Έμ€μ κ°λ°μ λ§μΆ€ν νλ‘νμ λ±λ‘νκ³ , λμ κΈ°μ κΆν©μ΄ μ λ§λ κΈ°μ λ€μ λ§€μΉ λ°μΌμΈμ.
programmers.co.kr
π« μ ν μ¬ν
- μ¬μ κ°μ nμ 1 μ΄μ 100 μ΄νμ λλ€.
- costsμ κΈΈμ΄λ ((n-1) * n) / 2μ΄νμ λλ€.
- μμμ iμ λν΄, costs[i][0] μ costs[i] [1]μλ λ€λ¦¬κ° μ°κ²°λλ λ μ¬μ λ²νΈκ° λ€μ΄μκ³ , costs[i] [2]μλ μ΄ λ μ¬μ μ°κ²°νλ λ€λ¦¬λ₯Ό 건μ€ν λ λλ λΉμ©μ λλ€.
- κ°μ μ°κ²°μ λ λ² μ£Όμ΄μ§μ§ μμ΅λλ€. λν μμκ° λ°λλλΌλ κ°μ μ°κ²°λ‘ λ΄ λλ€. μ¦ 0κ³Ό 1 μ¬μ΄λ₯Ό μ°κ²°νλ λΉμ©μ΄ μ£Όμ΄μ‘μ λ, 1κ³Ό 0μ λΉμ©μ΄ μ£Όμ΄μ§μ§ μμ΅λλ€.
- λͺ¨λ μ¬ μ¬μ΄μ λ€λ¦¬ κ±΄μ€ λΉμ©μ΄ μ£Όμ΄μ§μ§ μμ΅λλ€. μ΄ κ²½μ°, λ μ¬ μ¬μ΄μ 건μ€μ΄ λΆκ°λ₯ν κ²μΌλ‘ λ΄ λλ€.
- μ°κ²°ν μ μλ μ¬μ μ£Όμ΄μ§μ§ μμ΅λλ€.
π μ μΆλ ₯ μ
| n | costs | return |
| 4 | [[0,1,1],[0,2,2],[1,2,5],[1,3,1],[2,3,8]] | 4 |
π€ νμ΄ λ°©λ²
1οΈβ£ λ€μ΅μ€νΈλΌ (μ€ν¨ π βοΈ)
β‘οΈ λ€μ΅μ€νΈλΌλ₯Ό ν΅ν΄ νΉμ μ무 μ¬μμ μΆλ°νμ¬ μ΅μ λΉμ©μ ν©μ μΆλ ₯νλ©΄ λ κ² μ΄λΌκ³ μκ°νκ³ , μλμ κ°μ μ½λλ₯Ό μμ±νμλ€.
import java.util.Queue;
import java.util.PriorityQueue;
import java.util.ArrayList;
// Node ν΄λμ€ μ μ
class Node implements Comparable<Node> {
int index;
int cost;
public Node (int index, int cost) {
this.index = index;
this.cost = cost;
}
@Override
public int compareTo (Node o) {
return Integer.compare(this.cost, o.cost);
}
}
class Solution {
public int solution(int n, int[][] costs) {
int answer = 0;
// μ΅μ거리λ₯Ό λ΄μ λ°°μ΄
int[] minDist = new int[n];
// μ΅μλΉμ©μ λ΄μ λ°°μ΄
int[] minCost = new int[n];
// λ°°μ΄ μ΄κΈ°ν
int max = Integer.MAX_VALUE;
for (int i=0; i<n; i++) {
minDist[i] = max;
}
// μ
λ ₯κ° μ²λ¦¬
ArrayList<Node>[] graph = new ArrayList[n];
for (int i=0; i<n; i++) graph[i] = new ArrayList<>(); // μ΄κΈ°ν
for(int[] c : costs) {
graph[c[0]].add(new Node(c[1], c[2]));
graph[c[1]].add(new Node(c[0], c[2]));
}
// μμμ μ€μ
Queue<Node> pq = new PriorityQueue<>();
boolean[] visited = new boolean[n];
minDist[0] = 0;
pq.add(new Node(0, 0));
// νμ μμ
while(!pq.isEmpty()) {
int nowVertex = pq.poll().index;
if (visited[nowVertex]) continue;
visited[nowVertex] = true;
for (Node next : graph[nowVertex]) {
if (minDist[next.index] > minDist[nowVertex] + next.cost) {
// μ΅λ¨ 거리 κ° κ°±μ
minDist[next.index] = minDist[nowVertex] + next.cost;
// μ΅μ λΉμ© κ° κ°±μ
minCost[next.index] = next.cost;
// Queue μ½μ
pq.offer(new Node(next.index, minDist[next.index]));
}
}
}
// κ° κ³μ°
for (int i=1; i<n; i++) {
answer += minCost[i];
// System.out.printf("%dλ²μ§Έ : %d\n", i, minCost[i]);
}
return answer;
}
}
β‘οΈ μ΄λ κ² λ κ²½μ° μΆλ° μ§μ λ§λ€ μ΅μ λΉμ©μ΄ λ€λ₯΄κΈ° λλ¬Έμ λ°λ‘κ° μ겨 μ€ν¨νλ€.
2οΈβ£ λ€μ΅μ€νΈλΌλ₯Ό λͺ¨λ μΆλ° μ μμ μ§ν β‘οΈ νλ‘μ΄λ μμ (μ€ν¨ π βοΈ)
β‘οΈ 1οΈβ£ νμ΄μμ ν μμμ λ§ μ ν΄μ λ¬Έμ κ° μκΈ΄ κ² μ΄λ―λ‘ λ€μ΅μ€νΈλΌλ₯Ό λͺ¨λ μ¬μμ μ€νμμΌ νλ‘μ΄λ μμ μ ννλ‘ κ΅¬ννμλ€.
import java.util.Queue;
import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Collections;
// Node ν΄λμ€ μ μ
class Node implements Comparable<Node> {
// (ν΄λμ€ μ μ μ½λ μλ΅)
}
class Solution {
public int solution(int n, int[][] costs) {
int answer = 0;
// μ΅μ거리λ₯Ό λ΄μ λ°°μ΄
int[][] minDist = new int[n][n];
// μ΅μλΉμ©μ λ΄μ λ°°μ΄
int[][] minCost = new int[n][n];
// μ λ΅κ°λ€μ λ΄μ λ°°μ΄
ArrayList<Integer> answers = new ArrayList<>();
// λ°°μ΄ μ΄κΈ°ν
int max = Integer.MAX_VALUE;
for (int[] dist : minDist) {
for (int i=0; i<n; i++) {
dist[i] = max;
}
}
// μ
λ ₯κ° μ²λ¦¬
ArrayList<Node>[] graph = new ArrayList[n];
for (int i=0; i<n; i++) graph[i] = new ArrayList<>(); // μ΄κΈ°ν
for(int[] c : costs) {
graph[c[0]].add(new Node(c[1], c[2]));
graph[c[1]].add(new Node(c[0], c[2]));
}
// μμμ μ€μ
Queue<Node> pq = new PriorityQueue<>();
boolean[] visited = new boolean[n];
for (int start=0; start<n; start++) {
minDist [start][start] = 0;
pq.add(new Node(start, 0));
// νμ μμ
while(!pq.isEmpty()) {
int nowVertex = pq.poll().index;
if (visited[nowVertex]) continue;
visited[nowVertex] = true;
for (Node next : graph[nowVertex]) {
if (minDist[start][next.index] > minDist[start][nowVertex] + next.cost) {
// μ΅λ¨ 거리 κ° κ°±μ
minDist[start][next.index] = minDist[start][nowVertex] + next.cost;
// μ΅μ λΉμ© κ° κ°±μ
minCost[start][next.index] = next.cost;
// Queue μ½μ
pq.offer(new Node(next.index, minDist[start][next.index]));
}
}
}
// κ° κ³μ°
int sum = 0;
for (int i=0; i<n; i++) {
sum += minCost[start][i];
}
answers.add(sum);
visited = new boolean[n];
}
return Collections.min(answers);
}
}
β‘οΈ μ΄λ κ² μ½λλ₯Ό μμ±ν΄λ ν΅κ³Όνμ§ λͺ»νλ ν μ€νΈ μΌμ΄μ€λ€μ΄ μμλ€. μ μ΄μ μ κ·Ό μμ²΄κ° μλͺ»λμλ κ²μ΄λ€.
3οΈβ£ νμλ² (μ±κ³΅ πβοΈ)
β‘οΈ μκ°μ λ°κΏμ λ€μκ³Ό κ°μ΄ μ μνμλ€.
β : λͺ¨λ μ¬ μ°κ²° μ 보λ₯Ό μ μ₯νλ€.
β‘ : κ°μ₯ λΉμ©μ΄ λ§μ΄ λλ μ°κ²°μ λμ΄λΈλ€. (Greedy κ°λ )
β’ : μ°κ²°μ λμ΄λ΄λ μ¬μ΄ λͺ¨λ μ°κ²°λλμ§ νμΈνλ€. (DFS)
β£-1 : μ°κ²°λλ©΄ ν΄λΉ λΉμ©μ μ κ°μ΄ κ°λ₯νλ―λ‘ μ°κ²°μ λκ³ , κ³μ°μμ μ μΈμν¨λ€.
β£-2 : μ°κ²°λμ§ μμΌλ©΄ ν΄λΉ μ°κ²°μ μμ볡ꡬνκ³ , λΉμ©μ ν¬ν¨μν¨λ€.
β‘οΈ β‘ λ₯Ό μ½λλ‘ κ΅¬ννκΈ° μν΄ μ°μ μμ νλ₯Ό μ¬μ©νμλ€. costs μ λ ₯κ°λ€μ μ°μ μμ νμ λ΄μΌλ©° λ΄λ¦Όμ°¨μ μ λ ¬μ΄ λλλ‘ νμλλ°, μ΄λ₯Ό μν΄ Node ν΄λμ€ μ μΈμμ Comparable μΈν°νμ΄μ€λ₯Ό ꡬννμ¬ λ΄λ¦Όμ°¨μμΌλ‘ κΈ°μ€μ μ 립ν΄μ£Όμλ€.
class Node implements Comparable<Node> { // Comparable μΈν°νμ΄μ€ λμ
public int start;
public int end;
public int cost;
public Node (int start, int end, int cost) {
this.start = start;
this.end = end;
this.cost = cost;
}
@Override
public int compareTo(Node o) {
return Integer.compare(o.cost, this.cost); // λ΄λ¦Όμ°¨μ
}
}
Queue<Node> pq = new PriorityQueue<>();
for (int[] cost : costs) {
// μ°μ μμ νμ Node λ΄κΈ°
pq.offer(new Node(cost[0], cost[1], cost[2]));
}

β‘οΈ λΆκ·μΉνλ μ λ ₯κ°λ€μ΄ λ΄λ¦Όμ°¨μμΌλ‘ μ 리λ κ²μ λ³Ό μ μλ€.
β‘οΈ μμ κ°μ κ³Όμ μ ν΅ν΄μ λΉμ©μ΄ ν° κ°λΆν° μ°κ²°μ νμΈνλ©° μ΅λν μ°κ²°μ λμ΄λ΄μκ³ , ν μ€νΈ μΌμ΄μ€ λͺ¨λ ν΅κ³Ό νμλ€.

π» νμ΄ μ½λ
import java.util.Queue;
import java.util.PriorityQueue;
import java.util.ArrayList;
class Node implements Comparable<Node> {
public int start;
public int end;
public int cost;
public Node (int start, int end, int cost) {
this.start = start;
this.end = end;
this.cost = cost;
}
@Override
public int compareTo(Node o) {
return Integer.compare(o.cost, this.cost); // λ΄λ¦Όμ°¨μ
}
}
class Solution {
public static boolean[][] graph;
public static boolean[] visited;
public static int cnt = 1;
public static boolean done = false;
public int solution(int n, int[][] costs) {
int answer = 0;
visited = new boolean[n];
// (1) μ
λ ₯κ° λ΄κΈ°
Queue<Node> pq = new PriorityQueue<>();
graph = new boolean[n][n];
for (int[] cost : costs) {
// μ°μ μμ νμ Node λ΄κΈ°
pq.offer(new Node(cost[0], cost[1], cost[2]));
// μΈμ νλ ¬μ μ°κ²° λ°μ
graph[cost[0]][cost[1]] = true;
graph[cost[1]][cost[0]] = true;
}
// μ°μ μμ ν μ
λ ₯νμΈ : λ΄λ¦Όμ°¨μ νν
System.out.printf("μ°μ μμ ν νμΈ : ");
for (Node node : pq) {
System.out.printf("%d " , node.cost);
}
System.out.println();
// (2) Greedy μ μ©νλ©΄μ μ 체 νμ
while (!pq.isEmpty()) {
Node node = pq.poll(); // κ°μ₯ λΉμ©μ΄ ν° λ
Έλ [2,3,8]
// μ°κ²° λκΈ°
graph[node.start][node.end] = false;
graph[node.end][node.start] = false;
// μ°κ²° κ°λ₯ νμ
visited[0] = true;
System.out.printf("%d λΉΌκ³ μ°κ²° κ°λ₯ μ¬λΆ : ", node.cost);
if (isLinked(0, n)) { // κ²½μ° 1 : μ°κ²° κ°λ₯νλ©΄ μμ΄λ κ°λ₯νλ―λ‘ answer μ κ° μΆκ° μν¨
reset(n);
System.out.println("κ°λ₯");
continue;
}
// κ²½μ°2 : μ°κ²° λΆκ°λ₯νλ©΄ νμν κ°μ΄λ―λ‘ answer μ κ° μΆκ°
reset(n);
System.out.println("λΆκ°λ₯");
// μ°κ²° μμ볡ꡬ
graph[node.start][node.end] = true;
graph[node.end][node.start] = true;
answer += node.cost;
}
return answer;
}
// μ°κ²° νμ : DFS
public static boolean isLinked(int start, int n) {
if (done) return true;
for (int i=0; i<n; i++) {
if (start == i || visited[i]) continue;
if (graph[start][i]) {
visited[i] = true;
if (++cnt == n) done = true;
isLinked(i, n);
}
}
if (done) return true;
return false;
}
// μ°κ²° νμ ν μ΄κΈ°ν
public static void reset(int n) {
cnt = 1;
done = false;
visited = new boolean[n];
}
}
π§ μΆκ° 곡λΆ
1οΈβ£ ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦ (Kruscal)
β‘οΈ λ§μ§λ§ νμ΄ λ°©μμ΄ λ§€λ² DFS λ₯Ό ν΅ν΄ μ 체 μ°κ²°μ¬λΆλ₯Ό νμΈν΄μΌνλ€λ μ μμ λ Έλμ κ°μκ° λ§μμ§ μλ‘ λΆλ΄ κΈ°νκΈμμ μΌλ‘ λμ΄λ κ²μ΄λΌκ³ μκ°νκ³ , μΆκ°μ μΌλ‘ μκ³ λ¦¬μ¦μ 곡λΆνλ μ€ μ΅μ μ μ₯ νΈλ¦¬ κ°λ μ΄ μ μ©λ ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦μ λν΄ μκ² λμλ€. λ¨Όμ μ μ₯ νΈλ¦¬ (Spanning Tree) μ 쑰건μ ν¬κ² λκ°μ§μ΄λ€.

β μ¬μ΄ν΄μ΄ μ‘΄μ¬νμ§ μλλ€.
β‘ λͺ¨λ μ μ λ€μ΄ μ°κ²°λμ΄μλ€.
β‘οΈ μ λκ°μ§ 쑰건μ λ§μ‘±νλ©΄μ νΈλ¦¬λ₯Ό μμ±νκ² λλ©΄ μ΄ κ°μ μ κ°μκ° (n-1) κ°κ° λκ³ , μ΄ κΈ°λ³Έ 쑰건μμ μ΅μ κ°μ€μΉλ‘ κ°μ λ€μ ꡬμ±νλ©΄ κ·Έκ²μ μ΅μ μ μ₯ νΈλ¦¬ (MST = Minimum Spanning Tree) λΌκ³ νλ€.
β‘οΈ ν¬λ£¨μ€μΉΌ μκ³ λ¦¬μ¦μ κ²½μ° νμλ² (Greedy) λ₯Ό κΈ°λ³Έ κ°λ μΌλ‘ νλ€. μ£Όμ΄μ§ κ°μ λ€μμ μ΅μ λΉμ©μ κ°μ§ κ°μ λΆν° νμΈνλ©° νΈλ¦¬λ₯Ό ꡬμ±ν΄κ°λ€. μ΄ λ μ¬μ©λλ μλ£κ΅¬μ‘°λ λ£¨νΈ λ Έλλ₯Ό κΈ°λ‘νκΈ° μν parent λ°°μ΄μ΄κ³ , ν¨μλ νΉμ λ Έλμ λ£¨νΈ λ Έλλ₯Ό νμΈνλ findParent() μ λ£¨νΈ λ Έλκ° λ€λ₯Έ λ μ§ν©μ νλλ‘ λ¬Άλ unionParent() λ₯Ό μ μνμ¬ μ¬μ©νλ€. μλ μ리λ μλμ κ°λ€.
β : μ£Όμ΄μ§ κ°μ λ€μ λΉμ©μ κΈ°μ€μΌλ‘ μ€λ¦μ°¨μ μ λ ¬νλ€.
β‘ : κ°μ μ λ λ Έλλ€μ λ£¨νΈ λ Έλλ₯Ό νμΈνλ€.
β’-1 : κ°μΌλ©΄ μ°κ²°ν κ²½μ° μ¬μ΄ν΄μ΄ λ°μνλ―λ‘ λμ΄κ°λ€.
β’-2 : λ€λ₯΄λ©΄ μ μ₯ νΈλ¦¬μ 쑰건μ λ§μ‘±νλ―λ‘ λ μ§ν©μ ν©μΉκ³ , λΉμ©μ λ°μνλ€.
β£ : λͺ¨λ κ°μ μ λν΄μ β‘,β’ μ κ³Όμ μ λ°λ³΅νλ€.
β‘οΈ μ μ©λ μ½λλ μλμ κ°λ€.
import java.util.ArrayList;
import java.util.Collections;
class Node implements Comparable<Node> { // λ
Έλ ν΄λμ€ μ μΈ
int indexA, indexB, cost;
public Node (int indexA, int indexB, int cost) {
this.indexA = indexA;
this.indexB = indexB;
this.cost = cost;
}
@Override
public int compareTo (Node other) {
if (this.cost < other.cost) return -1;
return 1;
}
}
class Solution {
// root λ
Έλ κ°μ λ΄λ λ°°μ΄
public static int[] parent;
public int solution(int n, int[][] costs) {
int answer = 0;
// parent λ°°μ΄ μ΄κΈ°ν
parent = new int[n];
for (int i=0; i<n; i++) {
parent[i] = i;
}
// μ
λ ₯κ° μ²λ¦¬
ArrayList<Node> vertexList = new ArrayList<>();
for (int[] cost : costs) {
vertexList.add(new Node(cost[0], cost[1], cost[2]));
}
// μ λ ¬
Collections.sort(vertexList);
for (int i=0; i<vertexList.size(); i++) {
int from = vertexList.get(i).indexA;
int to = vertexList.get(i).indexB;
int cost = vertexList.get(i).cost;
// λ£¨νΈ μμκ° κ°μ§ μλ€λ©΄ μ¬μ΄ν΄μ΄ λ°μνμ§ μλ κ²μ΄λ―λ‘ λ¬Άμμ²λ¦¬
if (findParent(from) != findParent(to)) {
union(from, to);
answer += cost;
}
}
return answer;
}
public static int findParent(int x) {
if (parent[x] == x) return x;
return parent[x] = findParent(parent[x]);
}
public static void union(int a, int b) {
a = findParent(a);
b = findParent(b);
if (a < b) parent[b] = a;
else parent[a] = b;
}
}

'Algorithm π€' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
| (μκ³ λ¦¬μ¦ μ€ν°λ) (Programmers) νΈν λμ€ π¨ (0) | 2023.07.26 |
|---|---|
| (μκ³ λ¦¬μ¦ μ€ν°λ) (Programmers) νλ Έμ΄μ ν π° (0) | 2023.05.23 |
| μ΄λΆ νμ π (Binary Search) (0) | 2023.04.17 |
| κ·Έλνπ (Graph) (0) | 2023.03.21 |
| λμ κ³νλ²ποΈ (Dynamic Programming) (0) | 2023.03.13 |