ALGORITHM/BOJ

[백준] 1197 최소 스패닝 트리

0298 2020. 11. 7. 21:19

www.acmicpc.net/problem/1197

 

1197번: 최소 스패닝 트리

첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 정점과 B번 정점이

www.acmicpc.net

2020-11-07


# 스패닝 트리 (Spanning Tree)모든 정점들을 최소 간선의 수로 연결한 트리. 

  - 모든 정점이 연결이 되어 있어야 함

  - 사이클을 포함해서는 안됨

  - n개의 정점을 n-1개의 간선으로 연결

 

#최소 스패닝 트리(Minimum Spanning Tree)Spanning Tree에서 정점들을 연결한 간선들의 가중치 합이 최소인 트리.

  1) 크루스칼 (Kruskal) 알고리즘

     - 가중치가 가장 낮은 간선을 선택하고 정점들을 이어나감

     - 이 때, 사이클의 생성을 막기 위해 union-find를 사용함

  2) 프림(Prim) 알고리즘

     - 정점을 기준으로 함

 

 

// 최소 스패닝 트리
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

class Graph implements Comparable<Graph> {
	int start;
	int end;
	int weight;

	Graph(int start, int end, int weight) {
		this.start = start;
		this.end = end;
		this.weight = weight;
	}

	@Override
	public int compareTo(Graph o) {
		return this.weight - o.weight;
	}
}

public class Main1197 {
	public static int V, E, parent[], result;
	public static List<Graph> list;

	public static void union(int x, int y) {
		x = find(x);
		y = find(y);

		if (x != y) {
			parent[y] = x;
		}
	}

	public static int find(int x) {
		if(parent[x] == x) return x;
		return parent[x] = find(parent[x]);
	}

	public static void main(String[] args) throws Exception {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());
		V = Integer.parseInt(st.nextToken());
		E = Integer.parseInt(st.nextToken());
		list = new ArrayList<Graph>();
		parent = new int[V+1];
		result = 0;
		for(int i = 1; i <= V; i++) parent[i] = i;
		
		for (int i = 0; i < E; i++) {
			st = new StringTokenizer(bf.readLine());
			int start = Integer.parseInt(st.nextToken());
			int end = Integer.parseInt(st.nextToken());
			int weight = Integer.parseInt(st.nextToken());
			list.add(new Graph(start, end, weight));
		}

		Collections.sort(list);

		for(int i = 0; i < list.size(); i++) {
			int start = list.get(i).start;
			int end = list.get(i).end;
			if(find(start) != find(end)) {
				union(start, end);
				result += list.get(i).weight;
			}
		}
		
		System.out.println(result);
	}
}

 

크루스칼 알고리즘으로 풀었다.

 

1. parent 객체를 초기화 한다.

 

2. 가중치를 기준으로 오름차순 정렬을 한다.

 

3. 정렬한 가중치를 기준으로, 가중치가 작은 간선부터 체크한다.

 3-1) union-find를 이용하여 정점이 연결되어 있다면, union을 해주고 가중치를 더해준다.

 3-2) 이미 연결되어 있다면, 가중치를 더하지 않는다.

 

	@Override
	public int compareTo(Graph o) {
		return this.weight - o.weight;
	}

처음 제출 했을 때 compareTo 메서드에서 작을 때, 같을 때, 클 때 3가지 케이스를 모두 커버 못해서 틀렸었다.