백준 1647번 JAVA : 도시 분할 계획

문제

백준 문제 링크 : https://www.acmicpc.net/problem/1647

풀이전략

마을을 분리한 뒤 분리한 마을들 간의 최소신장트리를 구하는 문제이다. 나는 문제를 풀 때 먼저 전체 마을을 이으는 최소신장트리를 구하고, 여기서 가장 긴 도로의 길이를 빼줌으로써 마을을 2개로 분리할 것이다.

  • 크루스칼 알고리즘을 사용한다.

코드

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

public class Main {

	static class Edge{
		public int a, b, dis;
		public Edge(int a, int b, int dis){
			this.a = a;
			this.b = b;
			this.dis = dis;
		}
	}

	static int N, M;
	static int[] graph;
	static Edge[] edge;

	static int find(int n) {
		if(graph[n] == n) return n;
		return graph[n] = find(graph[n]);
	}

	static void union(int a, int b) {
		graph[find(a)] = find(b);
	}

	public static void main(String[] args) throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		int N = Integer.parseInt(st.nextToken());
		int M = Integer.parseInt(st.nextToken());

		graph = new int[N+1];
		for(int i=0; i<=N; i++) {
			graph[i] = i;
		}
		edge = new Edge[M];
		for(int i=0; i<M; i++) {
			st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());
			int c = Integer.parseInt(st.nextToken());
			edge[i] = new Edge(a,b,c);
		}


		Arrays.sort(edge, (e1, e2) -> e1.dis - e2.dis);
		int answer = 0;
		int lastCityDis = 0;
		for(int i=0; i<M; i++) {
			Edge now = edge[i];
			if(find(now.a) != find(now.b)) {
				union(now.a, now.b);
				answer+=now.dis;
				lastCityDis = now.dis;
			}
		}
		System.out.println(answer - lastCityDis);
	}
}

회고

  • 크루스칼알고리즘이 무엇인지, 최소신장트리가 무엇인지 안다면 쉽게 풀 수 있는 문제로, 약간 정석같은 문제였다.
  • 여기서 input으로 처음부터 분리된 마을이 들어온다면 어떻게 해야할까 하는 의문이 들었다.

Written by@Gomster
항상 노력하고 나아가는 백엔드 개발자가 되고 싶은 대학생입니다.

GitHub