백준 [1197] 최소 스패닝 트리
문제보기
풀이
- 주의사항
- 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)이기 때문에 Scanner와 차이가 많이난다.
- 정점의 갯수가 크기 때문에 배열을 사용한 인접행렬을 사용하면 메모리초과가 난다.
- 이 경우엔 Kruskal의 성능이 더 좋게 나왔다
소스코드 1. Kruskal 사용
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;
public class Main {
static int[] parents;
static int[] rank;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int V = Integer.parseInt(st.nextToken());
int E = Integer.parseInt(st.nextToken());
int[][] edges = new int[E][3];
for (int i = 0; i < E; i++) {
st = new StringTokenizer(br.readLine());
edges[i][0] = Integer.parseInt(st.nextToken()) - 1;
edges[i][1] = Integer.parseInt(st.nextToken()) - 1;
edges[i][2] = Integer.parseInt(st.nextToken());
}
Arrays.sort(edges, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
// TODO Auto-generated method stub
return Integer.compare(o1[2], o2[2]);
}
});
parents = new int[V];
rank = new int[V];
for (int i = 0; i < V; i++) {
makeSet(i);
}
int sum = 0;
for (int i = 0; i < E; i++) {
int px = findSet(edges[i][0]);
int py = findSet(edges[i][1]);
int c = edges[i][2];
if (px != py) {
sum += c;
union(px, py);
}
}
System.out.println(sum);
}
public static void makeSet(int x) {
parents[x] = x;
}
public static int findSet(int x) {
if (parents[x] == x)
return x;
parents[x] = findSet(parents[x]);
return parents[x];
}
public static void union(int px, int py) {
if (rank[px] > rank[py])
parents[py] = px;
else {
parents[px] = py;
if (rank[px] == rank[py])
rank[py]++;
}
}
}
소스코드 2. Prim 우선순위 큐 사용
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
static class Node implements Comparable<Node> {
int d;
int cost;
public Node(int d, int cost) {
this.d = d;
this.cost = cost;
}
@Override
public int compareTo(Node o) {
// TODO Auto-generated method stub
return Integer.compare(this.cost, o.cost);
}
}
static int V, E;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
V = Integer.parseInt(st.nextToken());
E = Integer.parseInt(st.nextToken());
List<Node>[] list = new ArrayList[V];
for (int i = 0; i < V; i++) {
list[i] = new ArrayList<>();
}
for (int i = 0; i < E; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken()) - 1;
int b = Integer.parseInt(st.nextToken()) - 1;
int cost = Integer.parseInt(st.nextToken());
list[a].add(new Node(b, cost));
list[b].add(new Node(a, cost));
}
boolean[] visited = new boolean[V];
PriorityQueue<Node> queue = new PriorityQueue<>();
visited[0] = true;
queue.addAll(list[0]);
int cnt = 0;
long sum = 0;
while (!queue.isEmpty()) {
if (cnt == V)
break;
Node node = queue.poll();
if (visited[node.d])
continue;
sum += node.cost;
queue.addAll(list[node.d]);
visited[node.d] = true;
cnt++;
}
System.out.println(sum);
}
}