SWEA 3124 - 최소 스패닝 트리

Updated:

Java

3124 번 - 최소 스패닝 트리

문제

그래프가 주어졌을 때, 그 그래프의 최소 스패닝 트리를 구하는 프로그램을 작성하시오.

접근 방법

크루스칼 알고리즘을 통하여 해결하였다.
주의 할 점은, 정점과 간선의 수가 굉장히 많고 그 값도 크므로 가중치의 합을 저장할 변수를 Long으로 선언해야한다.
또한, union 코드에서,

int Min_Parent = Math.min(aRoot, bRoot);	// 최대한 한쪽으로 몰아 넣는다.
parents[aRoot] = Min_Parent;	
parents[bRoot] = Min_Parent;	

처럼 한쪽 부모로 몰아넣어, 이후 findSet의 작업을 줄여준다.

코드

import java.io.*;
import java.util.*;

class Solution {
	static int n, m;
	static int[] parents;
	static Edge[] edgeList;
	// 간선
	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);
		}

		@Override
		public String toString() {
			StringBuilder builder = new StringBuilder();
			builder.append("[").append(from).append(", ").append(to).append(", ").append(weight)
					.append("]");
			return builder.toString();
		}
		
	}
	//------------ 서로소 집합-------------//
	// 각 사람들을 초기화 해준다.
	// 처음은 다 자기 자신이 부모
	static void make() {
		for(int i = 1; i <= n; i++) {
			parents[i] = i;
		}
	}
	
	static int findSet(int num) {
		// 자신이 root이면 반환
		if(parents[num] == num)
			return num;
		// path compression을 하여 해당 노드를 최상위 노드 바로 밑에 붙게 한다.
		return parents[num] = findSet(parents[num]);
	}
	
	static boolean union(int a, int b) {
		int aRoot = findSet(a);
		int bRoot = findSet(b); 
		if(aRoot == bRoot)		// a와 b의 root가 같으면, 같은 집합이므로 종료
			return false;
		int Min_Parent = Math.min(aRoot, bRoot);	// 최대한 한쪽으로 몰아 넣는다.
		parents[aRoot] = Min_Parent;	
		parents[bRoot] = Min_Parent;	
		return true;
	}
	
	public static void main(String []args) throws Exception {  
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer stk;
    	int tc = stoi(br.readLine());
    	
    	for(int tidx = 1; tidx <= tc; tidx++) {
    		stk = new StringTokenizer(br.readLine());
    		n = stoi(stk.nextToken());
    		m = stoi(stk.nextToken());
    		edgeList = new Edge[m];
    		parents = new int[n + 1];
    		
    		for(int i = 0; i < m; i++) {
    			stk = new StringTokenizer(br.readLine());
    			edgeList[i] = new Edge(stoi(stk.nextToken()), stoi(stk.nextToken()), stoi(stk.nextToken()));
    		}
    		
    		Arrays.sort(edgeList);	// 가중치가 적은 순으로 간선들을 정렬한다.
    		
    		
    		make();
        	long result = 0;
        	int count = 0; // 선택한 간선 수
        	
        	for(Edge edge : edgeList) {
        		if(union(edge.from, edge.to)) {		// 만약 사이클이 존재하게 되면 root가 같으므로, 해당 간선은 넘긴다. 
        			result += edge.weight;
        			if(++count == n - 1) {
        				break;
        			}
        		}
        	}
    		
    		System.out.println("#" + tidx + " " + result);
    	}
    	
	}
	
	static int stoi(String str) {
    	return Integer.parseInt(str);
    }
}

총평

난이도

⭐⭐★★★

후기

개선할 점