[SWEA] 1251.하나로

Kruskal Algorithm

  • 메모리 : 96,264 KB

  • 실행시간 : 878 ms

  • 코드길이 : 2,387 B

  • 소요시간 : 1H

package SWExpert;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Solution_D4_1251_하나로_Kruskal {

	static long[] X;
	static long[] Y;
	static long[][] graph;
	static int[] parents;

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder answer = new StringBuilder();
		int T = Integer.parseInt(in.readLine());

		for (int tc = 1; tc <= T; tc++) {
			answer.append('#').append(tc).append(' ');
			int N = Integer.parseInt(in.readLine());
			X = new long[N];
			Y = new long[N];
			StringTokenizer st = new StringTokenizer(in.readLine(), " ");
			for (int i = 0; i < N; i++) {
				X[i] = Long.parseLong(st.nextToken());
			}
			st = new StringTokenizer(in.readLine(), " ");
			for (int i = 0; i < N; i++) {
				Y[i] = Long.parseLong(st.nextToken());
			}

			double E = Double.parseDouble(in.readLine());
			int size = N * (N - 1) / 2;
			graph = new long[size][3];
			int cnt = 0;
			for (int i = 0; i < N - 1; i++) {
				for (int j = i + 1; j < N; j++) {
					graph[cnt][0] = i;
					graph[cnt][1] = j;
					graph[cnt][2] = (long) (Math.pow(X[i] - X[j], 2) + Math.pow(Y[i] - Y[j], 2));
					cnt++;
				}
			}

			Arrays.sort(graph, new Comparator<long[]>() {
				@Override
				public int compare(long[] o1, long[] o2) {
					return Long.compare(o1[2], o2[2]);
				}

			});

			parents = new int[N];
			for (int i = 0; i < N; i++) {
				makeSet(i);
			}
			cnt = 0;
			double result = 0;
			for (int i = 0; i < size; i++) {
				int a = findSet((int) graph[i][0]);
				int b = findSet((int) graph[i][1]);
				// 같은 팀이라면 패스
				if (a == b)
					continue;
				// 간선이 연결하는 두 정점이 같은 팀이 아니라면 한팀으로 합쳐주고 간선선택
				union(a, b);
				result += graph[i][2];
				cnt++;
				if (cnt == N - 1)
					break;
			}
			result *= E;
			answer.append(Math.round(result)).append('\n');
		}

		System.out.print(answer);
		in.close();
	}

	static void makeSet(int x) {
		parents[x] = x;
	}

	static int findSet(int x) {
		if (x == parents[x])
			return x;
		else {
			parents[x] = findSet(parents[x]);
			return (int) parents[x];
		}
	}

	static void union(int x, int y) {
		int px = findSet(x);
		int py = findSet(y);
		parents[py] = px;
	}

}

Prim Algorithm1

  • 메모리 : 60,320 kb

  • 시간 : 466 ms

  • 코드길이 : 2,601

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Solution_D4_1251_하나로_Prim {

	static int N;
	static long[][] island;
	static long[][] graph;
	static double E;

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder answer = new StringBuilder();
		int T = Integer.parseInt(in.readLine());

		for (int t = 1; t <= T; t++) {
			answer.append("#").append(t).append(" ");
			N = Integer.parseInt(in.readLine());
			island = new long[N][2];

			// X좌표 입력.
			StringTokenizer xLine = new StringTokenizer(in.readLine(), " ");
			// Y좌표 임력.
			StringTokenizer yLine = new StringTokenizer(in.readLine(), " ");
			for (int i = 0; i < N; i++) {
				island[i] = new long[] { Integer.parseInt(xLine.nextToken()), Integer.parseInt(yLine.nextToken()) };
			}
			E = Double.parseDouble(in.readLine());

			// 입력된 자료를 기반으로 섬 간의 가중치 그래프 구하기.
			graph = new long[N][N];
			long[] from, to;
			for (int r = 0; r < N; r++) {
				from = island[r];
				for (int c = r + 1; c < N; c++) {
					to = island[c];
					graph[c][r] = graph[r][c] = (from[0] - to[0]) * (from[0] - to[0])
							+ (from[1] - to[1]) * (from[1] - to[1]);
				}
			}

			double cost = prim(0) * E;
			answer.append(Math.round(cost)).append("\n");

		} // end test-case

		System.out.print(answer);
		in.close();
	}

	private static double prim(int start) {

		// MST에 들어가지 않은 녀석들.
		PriorityQueue<Edge> pq = new PriorityQueue<>();
		// 모든 정점들을 다 관리.
		Edge[] dynamicGraph = new Edge[N];

		for (int n = 0; n < N; n++) {
			dynamicGraph[n] = new Edge(n, Long.MAX_VALUE);
			if (n == start) {
				dynamicGraph[n].cost = 0;
			}
			pq.add(dynamicGraph[n]);
		}
		long cost = 0;

		while (!pq.isEmpty()) {
			Edge front = pq.poll(); // MST에 포함되는 녀석.
			cost += front.cost;

			// 자식 탐색.
			for (int i = 0; i < N; i++) {
				Edge child = dynamicGraph[i];
				// pq : 비MST.
				if (pq.contains(child)) {
					long tempCost = graph[front.idx][child.idx];
					if (tempCost < child.cost) {
						child.cost = tempCost;
						pq.remove(child);
						pq.offer(child);
					}
				}
			}
		}

		return cost;
	}

	static class Edge implements Comparable<Edge> {
		int idx;
		long cost;

		public Edge(int idx, long cost) {
			super();
			this.idx = idx;
			this.cost = cost;
		}

		@Override
		public int compareTo(Edge o) {
			return Long.compare(this.cost, o.cost);
		}

	}
}

Prim Algorithm2

  • 메모리 : 49,284 KB

  • 실행시간 : 251 ms

  • 코드길이 : 2,029 B

  • 소요시간 : 40M


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Solution_D4_1251_하나로_Prim2 {

	static long[][] island;
	static long[][] graph;
	static int[] parents;

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder answer = new StringBuilder();
		int T = Integer.parseInt(in.readLine());

		for (int tc = 1; tc <= T; tc++) {
			answer.append('#').append(tc).append(' ');
			int N = Integer.parseInt(in.readLine());
			island = new long[N][2];
			StringTokenizer stX = new StringTokenizer(in.readLine(), " ");
			StringTokenizer stY = new StringTokenizer(in.readLine(), " ");
			for (int i = 0; i < N; i++) {
				island[i][0] = Long.parseLong(stX.nextToken());
				island[i][1] = Long.parseLong(stY.nextToken());
			}

			double E = Double.parseDouble(in.readLine()); // 입력완료
			graph = new long[N][N];
			for (int i = 0; i < N - 1; i++) {
				for (int j = i + 1; j < N; j++) {
					graph[i][j] = graph[j][i] = (long) (Math.pow(island[i][0] - island[j][0], 2)
							+ Math.pow(island[i][1] - island[j][1], 2));
				}
			}

			boolean[] check = new boolean[N];
			long[] key = new long[N];
			int[] p = new int[N];

			Arrays.fill(key, Long.MAX_VALUE);

			p[0] = -1;
			key[0] = 0;

			for (int i = 0; i < N - 1; i++) {
				long min = Long.MAX_VALUE;
				int index = -1;
				for (int j = 0; j < N; j++) {
					if (!check[j] && key[j] < min) {
						index = j;
						min = key[j];
					}
				}

				check[index] = true;
				for (int j = 0; j < N; j++) {
					if (!check[j] && graph[index][j] > 0 && key[j] > graph[index][j]) {
						p[j] = index;
						key[j] = graph[index][j];
					}
				}
			}
			double result = 0;
			for (int i = 0; i < N; i++) {
				result += key[i];
			}
			result *= E;
			answer.append(Math.round(result)).append('\n');
		} // end test-case

		System.out.print(answer);
		in.close();
	}
}

Leave a comment