
문제 설명
일반적인 최소스패닝 트리(MST) 문제입니다.
크루스칼 알고리즘과 프림 알고리즘으로 해결해봤습니다.
런타임 에러1
이 문제는 테스트 케이스가 여러개 들어옵니다. 마지막 0 0 입력이 왜 있는가 했더니,,
결국 이 문제점을 뒤늦게 이해하고 코드 수정을 하여 AC를 받았습니다.
즉, 0 0이 입력되기 전까지 테스트 케이스가 무한대로 들어오니 M,N 값을 검증해야 합니다.
if(M==0 && N==0)
	return;런타임 에러2
전혀 생각지 못했던 이유였습니다.
하단 소스코드엔 while문 밖으로 선언되어 있지만 아래처럼 while문 내에 삽입했더니 발생했습니다.
while(true){
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    //Your Code
}
위와 같이 BufferedReader 선언을 반복문 내에 넣었더니 계속해서 ArrayIndexOutOfBounds가 발생합니다.
늘 새로운 상황의 에러가 저를 반겨주니 감개무량하네요.
이 에러도 정확한 원인을 파악해보고 수정하도록 하겠습니다.
소스 코드
Java8 크루스칼
import java.util.*;
import java.io.*;
public class Main_kruskal {
	static StringBuilder sb = new StringBuilder();
	static int N,M,parent[];
	static int getParent(int x) {
		if(parent[x] == x)return x;
		return parent[x] = getParent(parent[x]);
	}
	static void unionParent(int a,int b) {
		a = getParent(a);
		b = getParent(b);
		if(a<b)parent[b]=a;
		else parent[a]=b;
	}
	static void input() throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		while(true) {
			st = new StringTokenizer(br.readLine());
			M = Integer.parseInt(st.nextToken());//집의수
			N = Integer.parseInt(st.nextToken());//길의수
			if(M==0 && N==0)break;
			parent = new int[M];
			for(int i =0;i<M;i++)parent[i]=i;
			class Edge{
				int from,to,dist;
				public Edge(int from, int to, int dist) {this.from = from;this.to = to;this.dist = dist;}			
			}
			ArrayList<Edge> query = new ArrayList<>();
			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 d = Integer.parseInt(st.nextToken());
				total+=d;
				query.add(new Edge(a,b,d));
			}
			Collections.sort(query,(o1,o2)->o1.dist-o2.dist);
			int answer =0;
			for(Edge edge:query) {
				int a = edge.from;
				int b = edge.to;
				if(getParent(a)==getParent(b))continue;
				unionParent(a,b);
				answer+=edge.dist;
			}
			sb.append(total-answer).append("\n");
		}		
	}
	public static void main(String[] args) throws IOException {
		input();
		System.out.println(sb);
	}
}Java8 프림
import java.util.*;
import java.io.*;
public class Main_Prim {
	static StringBuilder sb = new StringBuilder();
	static int N,M;
	static boolean visited[];
	static class Edge implements Comparable<Edge>{
		int node,dist;
		public Edge(int node, int dist) {this.node = node;this.dist = dist;}
		@Override
		public int compareTo(Edge o) {			
			return this.dist-o.dist;
		}		
	}
	static void input() throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		while(true) {
			st = new StringTokenizer(br.readLine());
			M = Integer.parseInt(st.nextToken());//집의수
			N = Integer.parseInt(st.nextToken());//길의수
			if(M==0 && N==0)break;
			visited = new boolean[M];
			ArrayList<ArrayList<Edge>> query = new ArrayList<>();
			for(int i =0;i<M;i++)query.add(new ArrayList<>());
			int totalCost = 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 d = Integer.parseInt(st.nextToken());
				totalCost+=d;
				query.get(a).add(new Edge(b,d));
				query.get(b).add(new Edge(a,d));
			}
			PriorityQueue<Edge> pq = new PriorityQueue<>();
			for(Edge cur:query.get(0))
				pq.add(cur);//임의의 정점 0부터 시작한다.
			visited[0]=true;
			int minCost =0;
			while(!pq.isEmpty()) {
				Edge edge = pq.poll();
				if(visited[edge.node])continue;//이미 방문했다면
				visited[edge.node]=true;				
				minCost+=edge.dist;				
				for(Edge next:query.get(edge.node)) {
					pq.add(next);//다음 pq에 추가
				}
			}
			sb.append(totalCost-minCost).append("\n");
		}		
	}
	public static void main(String[] args) throws IOException {
		input();
		System.out.println(sb);
	}
}

 
                               
                               
                              