[Algorithm] SWEA_최소스패닝트리
목차
MST 알고리즘 선택 기준
- 간선이 많으면 프림, 간선이 적으면 크루스칼.
- 외우는 법: “간(선)많(으면)프(림), 간(선)적(으면)쿠(르스칼)” - by 효인샘
2147483647(Integer.MAX_VALUE)도 외워두자: “21 47 48 36 47”.
우선순위 큐(PQ)와 방문 처리
- 일반 큐 기반 BFS에서는 넣을 때 방문 처리하는 것이 기본이다(무조건 방문 처리).
- 일반 큐는 넣는 순서가 바뀌지 않기 때문이다.
- 하지만 우선순위 큐(PQ)를 쓸 때 넣을 때 방문 처리를 하면 큰일 난다. 왜?
- PQ는 이미 가중치 순서대로 정렬되어 처리되고, 넣을 때마다 위치가 알아서 바뀌기 때문이다.
- 그래서 PQ에서는 넣을 때 방문 처리하지 않고, 꺼낼 때 방문 처리한다.
참고: Eclipse에서
Ctrl + Shift + O는 import 자동 정렬 단축키.
코드 (프림 + PQ + 인접 리스트)
package a0419.add;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Solution_d4_3124_최소스패닝트리_MST3_PrimPQListTest {
static class Edge implements Comparable<Edge>{
int from,to,weight;
public Edge(int from, int to, int weight) {
super();
this.from = from;
this.to = to;
this.weight = weight;
}
@Override
public int compareTo(Edge o) {
return Integer.compare(this.weight, o.weight);
}
}
public static void main(String args[]) throws Exception{
System.setIn(new FileInputStream("res/input_d4_3124.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb=new StringBuilder();
int T=Integer.parseInt(br.readLine());
for(int tc=1; tc<=T; tc++){
StringTokenizer st = new StringTokenizer(br.readLine()," ");
int V = Integer.parseInt(st.nextToken());
int E = Integer.parseInt(st.nextToken());
//int[][] adjMatrix = new int[V][V];
List<Edge>[] adjList=new ArrayList[V];
for (int i = 0; i < V; i++) {
adjList[i] = new ArrayList<Edge>();
}
boolean[] visited = new boolean[V];
long[] minEdge = new long[V];
for (int i = 0; i < V; i++) {
minEdge[i] = Long.MAX_VALUE;
}
for (int i = 0; i < E; i++) {
st = new StringTokenizer(br.readLine()," ");
int from = Integer.parseInt(st.nextToken())-1;
int to = Integer.parseInt(st.nextToken())-1;
int weight = Integer.parseInt(st.nextToken());
//adjMatrix[from][to] = weight;
//adjMatrix[to][from] = weight;
adjList[from].add(new Edge(from,to,weight));
adjList[to].add(new Edge(to,from,weight));
}
long result = 0;
minEdge[0] = 0;
PriorityQueue<Vertex> queue = new PriorityQueue<Vertex>();
queue.offer(new Vertex(0, minEdge[0]));
int cnt = 0; // 정점 개수
while(!queue.isEmpty()) {
Vertex minVertex = queue.poll();
if(visited[minVertex.no]) continue;
result += minVertex.cost;
visited[minVertex.no] = true;
if(++cnt == V) break;
//for (int i = 0; i < V; i++) {
// if(!visited[i] && adjMatrix[minVertex.no][i] != 0 &&
// minEdge[i] > adjMatrix[minVertex.no][i]) {
// minEdge[i] = adjMatrix[minVertex.no][i];
// queue.offer(new Vertex(i,minEdge[i]));
// }
//}
for (Edge edge:adjList[minVertex.no]) {
if(!visited[edge.to] && edge.weight != 0 &&
minEdge[edge.to] > edge.weight) {
minEdge[edge.to] = edge.weight;
queue.offer(new Vertex(edge.to,minEdge[edge.to]));
}
}
}
sb.append("#").append(tc).append(" ").append(result).append("\n");
}
System.out.print(sb.toString());
br.close();
}
static class Vertex implements Comparable<Vertex>{
int no;
long cost;
public Vertex(int no, long cost) {
this.no = no;
this.cost = cost;
}
@Override
public int compareTo(Vertex o) {
return Long.compare(this.cost, o.cost);
}
}
}