그래프의 모든 정점을 사이클 없이 잇는 트리에서 간선의 가중치의 합이 최소가 되는 트리
그러면 어떻게 구할 수 있을까?
바로 이 두 방법이 유명한 MST알고리즘인 KRUSKAL 알고리즘과 PRIM 알고리즘이다.
간선 중심으로 최소 신장 트리를 구하는 알고리즘
※ 사이클 여부는 어떻게 확인 ? Union-Find를 사용하자
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
static int N;
static int[] p;
static class Node implements Comparable<Node>{
int a;
int b;
int cost;
public Node(int a, int b, int cost) {
this.a = a;
this.b = b;
this.cost = cost;
}
@Override
public int compareTo(Node o) {
return cost - o.cost;
}
}
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader((new InputStreamReader(System.in)));
N = Integer.parseInt(br.readLine());
int M = Integer.parseInt(br.readLine());
p = new int[N+1];
for (int i = 0; i <= N; i++) p[i] = i;
PriorityQueue<Node> pq = new PriorityQueue<>();
for (int i = 0; i < M; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int cost = Integer.parseInt(st.nextToken());
pq.offer(new Node(a, b, cost));
}
int edgeCnt = 0;
int ans = 0;
while (edgeCnt != N-1) {
Node now = pq.poll();
if (union(now.a, now.b)) {
edgeCnt++;
ans += now.cost;
}
}
System.out.println(ans);
br.close();
}
static boolean union(int x, int y) {
int pX = find(x);
int pY = find(y);
if (pX == pY) return false;
if (pX < pY) p[pX] = pY;
else p[pY] = pX;
return true;
}
static int find(int x) {
if (p[x] == x) return x;
return p[x] = find(p[x]);
}
}
정점 중심으로 최소 신장 트리를 구하는 알고리즘
package blog;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class MST_Prim {
static class Edge {
int to;
int cost;
public Edge(int to, int cost) {
this.to = to;
this.cost = cost;
}
}
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
while (true) {
StringTokenizer st = new StringTokenizer(br.readLine());
int m = Integer.parseInt(st.nextToken());
int n = Integer.parseInt(st.nextToken());
if (m == 0 && n == 0) break;
ArrayList<ArrayList<Edge>> edgeList = new ArrayList<>();
for (int i = 0; i < m; i++) edgeList.add(new ArrayList<>());
PriorityQueue<Edge> pq = new PriorityQueue<>((o1, o2)->(o1.cost-o2.cost));
int total = 0;
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int cost = Integer.parseInt(st.nextToken());
edgeList.get(a).add(new Edge(b, cost));
edgeList.get(b).add(new Edge(a, cost));
total += cost;
}
boolean[] isVisited = new boolean[m];
int useCost = 0;
pq.offer(new Edge(0, 0));
while(!pq.isEmpty()) {
Edge now = pq.poll();
if (isVisited[now.to]) continue;
isVisited[now.to] = true;
useCost += now.cost;
for (Edge edge : edgeList.get(now.to)) {
if (!isVisited[edge.to]) pq.offer(edge);
}
}
sb.append(total-useCost).append("\n");
}
System.out.print(sb);
br.close();
}
}
혁이님의 최소 신장은 몇센치인가요 ?