https://www.acmicpc.net/problem/1197
최소 신장 트리의 기본 문제
그래프에서 노드간 가중치가 최소가 되는 트리를 의미

이를 해결하는 대표적인 알고리즘이 두가지 있다
프림은 임의의 한 정점에서 시작하여 그 정점의 간선들중 가장 작은 가중치(참고로 이전 정점들의 간선들을 포함하여)의 간선을 따라가는 방식이다.
과정
순서도

코드
import java.io.*;
import java.util.*;
public class Main {
private static int V;
private static int E;
private static List<int[]>[] graph;
private static boolean[] visited;
private static int minCost;
public static void main(final String[] args) throws IOException {
problem(new InputStreamReader(System.in));
}
public static void problem(final InputStreamReader isr) throws IOException {
init(new BufferedReader(isr));
prim(1);
System.out.println(minCost);
}
private static void init(final BufferedReader br) throws IOException {
StringTokenizer st = new StringTokenizer(br.readLine());
V = Integer.parseInt(st.nextToken());
E = Integer.parseInt(st.nextToken());
graph = new List[V+1];
visited = new boolean[V+1];
minCost = 0;
for (int i = 1; i < V+1; i++) {
graph[i] = new ArrayList<>();
}
for (int i = 0; i < E; i++) {
st = new StringTokenizer(br.readLine());
final int start = Integer.parseInt(st.nextToken());
final int end = Integer.parseInt(st.nextToken());
final int weight = Integer.parseInt(st.nextToken());
graph[start].add(new int[]{end,weight});
graph[end].add(new int[]{start,weight});
}
}
private static void prim(final int start){
final PriorityQueue<int[]> priorityQueue = new PriorityQueue<>((o1, o2)->o1[1] - o2[1]);
priorityQueue.add(new int[]{start,0});
while(!priorityQueue.isEmpty()){
final int[] edge = priorityQueue.poll();
if (visited[edge[0]]){
continue;
}
visited[edge[0]] = true;
minCost += edge[1];
for (final int[] nextEdge : graph[edge[0]]){
priorityQueue.add(nextEdge);
}
}
}
}
모든 간선을 가중치를 오름차순 기준으로 정렬한 후 사이클이 형성하지 않은 간선들을 추가해나가는 방식
Union&find 자료구조
과정
순서도

코드
import java.io.*;
import java.util.*;
public class Main {
private static int V;
private static int E;
private static int[][] graph;
private static int[] parent;
private static int minCost;
public static void main(final String[] args) throws IOException {
problem(new InputStreamReader(System.in));
}
public static void problem(final InputStreamReader isr) throws IOException {
final BufferedReader br = new BufferedReader(isr);
StringTokenizer st = new StringTokenizer(br.readLine());
V = Integer.parseInt(st.nextToken());
E = Integer.parseInt(st.nextToken());
minCost = 0;
graph = new int[E][3];
parent = new int[V+1];
for (int i = 1; i < V+1; i++) {
parent[i] = i;
}
for (int i = 0; i < E; i++) {
st = new StringTokenizer(br.readLine());
graph[i][0] = Integer.parseInt(st.nextToken());
graph[i][1] = Integer.parseInt(st.nextToken());
graph[i][2] = Integer.parseInt(st.nextToken());
}
Arrays.sort(graph, (o1,o2) -> o1[2] - o2[2]);
for (int i = 0; i < E; i++) {
kruskal(i);
}
System.out.println(minCost);
}
private static void kruskal(final int v){
if (find(graph[v][0]) != find(graph[v][1])){
union(graph[v][0],graph[v][1]);
minCost += graph[v][2];
}
}
private static void union(final int a, final int b){
final int aParent = find(a);
final int bParent = find(b);
if (aParent > bParent){
parent[aParent] = bParent;
return;
}
parent[bParent] = aParent;
}
private static int find(final int x){
if (parent[x] == x){
return x;
}
parent[x] = find(parent[x]);
return parent[x];
}
}