티스토리 뷰

Algorithm

SW Expert Academy_하나로

Young_J 2020. 9. 3. 13:31

 

프림과 크루스칼을 이용한 MST 구하는 문제

프림과 크루스칼의 차이 : 프림은 정점의 리스트를 크루스칼은 간선의 리스트를 저장해야 한다!!

※ 간만프 간적쿠 (공식처럼 외우기) 

* 프림과 다익스트라 코드가 비슷하니 잘 이해하고 넘어가자

 

Prim

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

public class 하나로_prim {
	static int T, N, arr[][];
	static double E;

	static class Point implements Comparable<Point> {
		int to;
		long cost;

		public Point(int v, long cost) {
			super();
			this.to = v;
			this.cost = cost;
		}

		@Override
		public int compareTo(Point o) {

			return Long.compare(this.cost, o.cost);
		}

	}

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

		for (int tc = 1; tc <= T; tc++) {
			N = Integer.parseInt(br.readLine());

			arr = new int[N][2];
			ArrayList<Point>[] list = new ArrayList[N];

			for (int i = 0; i < list.length; i++) {
				list[i] = new ArrayList<Point>();
			}

			StringTokenizer st = new StringTokenizer(br.readLine());
			for (int i = 0; i < N; i++) { // x좌표 입력받기
				arr[i][0] = Integer.parseInt(st.nextToken());
			}
			st = new StringTokenizer(br.readLine());
			for (int i = 0; i < N; i++) { // y좌표 입력받기
				arr[i][1] = Integer.parseInt(st.nextToken());
			}

			E = Double.parseDouble(br.readLine());

			// 알고리즘
			// 프림 알고리즘 최소신장트리 구하는 문제
			// 비용 계산하는게 관건임. 좌표로 잘 나와있으니 빼서 제곱해서 구하면 됨.
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < N; j++) {
					list[i].add(new Point(j, (long) Math.pow(Math.abs(arr[i][0] - arr[j][0]), 2)
							+ (long) Math.pow(Math.abs(arr[i][1] - arr[j][1]), 2)));
				}
			}

			long[] dist = new long[N];
			boolean[] v = new boolean[N];

			PriorityQueue<Point> pq = new PriorityQueue<Point>();
			Arrays.fill(dist, Long.MAX_VALUE);

			dist[0] = 0;
			pq.add(new Point(0, dist[0]));
			int cnt = 0;

			Point current = null;
			while (!pq.isEmpty()) {
				current = pq.poll();
				if (v[current.to]) {
					continue;
				}
				cnt++;
				if (cnt == N) {
					break;
				}

				v[current.to] = true;
				int size = list[current.to].size();
				for (int i = 0; i < size; i++) {
					if (!v[list[current.to].get(i).to]
							&& list[current.to].get(i).cost < dist[list[current.to].get(i).to]) {
						dist[list[current.to].get(i).to] = list[current.to].get(i).cost;
						pq.add(new Point(list[current.to].get(i).to, dist[list[current.to].get(i).to]));
					}
				}

			}

			long Ans = 0;

			for (Long l : dist) {
				Ans += l;
			}

			System.out.printf("#%d %d\n", tc, (long) Math.round(Ans * E));

//			print(arr);

		}
	}

//	private static void print(int[][] arr) {
//		for (int i = 0; i < arr.length; i++) {
//			for (int j = 0; j < arr[i].length; j++) {
//				System.out.print(arr[i][j] + " ");
//			}
//			System.out.println();
//		}
//	}

}

 

Kruskal

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;

public class 하나로_kruskal {
	static int T, N, arr[][], parents[];
	static double E;

	static class Point implements Comparable<Point> {
		int v;
		int w;
		long cost;

		public Point(int v, int w, long cost) {
			super();
			this.v = v;
			this.w = w;
			this.cost = cost;
		}

		@Override
		public int compareTo(Point o) {

			return Long.compare(this.cost, o.cost);
		}

	}

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

		for (int tc = 1; tc <= T; tc++) {
			N = Integer.parseInt(br.readLine());

			arr = new int[N][2];
			parents = new int[N];
			ArrayList<Point> list = new ArrayList<Point>();

			StringTokenizer st = new StringTokenizer(br.readLine());
			for (int i = 0; i < N; i++) { // x좌표 입력받기
				arr[i][0] = Integer.parseInt(st.nextToken());
			}
			st = new StringTokenizer(br.readLine());
			for (int i = 0; i < N; i++) { // y좌표 입력받기
				arr[i][1] = Integer.parseInt(st.nextToken());
			}

			E = Double.parseDouble(br.readLine());
			
			//알고리즘
			//크루스칼 알고리즘 최소신장트리 구하는 문제
			//비용 계산하는게 관건임. 좌표로 잘 나와있으니 빼서 제곱해서 구하면 됨.
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < N; j++) {
					list.add(new Point(i, j, (long) Math.pow(Math.abs(arr[i][0] - arr[j][0]), 2)
							+ (long) Math.pow(Math.abs(arr[i][1] - arr[j][1]), 2)));
				}
			}

			// parents초기화
			makeSet(parents);
			Collections.sort(list);

			double Ans = 0;
			int cnt = 0;
			for (Point lists : list) {
				if (union(lists.v, lists.w)) {
					Ans += lists.cost;
					if (++cnt == N - 1) {
						break;
					}

				}

			}

			System.out.printf("#%d %d\n", tc, (long) Math.round(Ans * E));

//			print(arr);

		}
	}

	private static boolean union(int x, int y) {
		int xx = find(x);
		int yy = find(y);

		if (xx == yy)
			return false;
		parents[yy] = xx;
		return true;
	}

	private static int find(int x) {
		if (parents[x] == x) {
			return x;
		}
		return parents[x] = find(parents[x]);

	}

	private static void makeSet(int[] parents) {

		for (int i = 0; i < parents.length; i++) {
			parents[i] = i;
		}

	}

//	private static void print(int[][] arr) {
//		for (int i = 0; i < arr.length; i++) {
//			for (int j = 0; j < arr[i].length; j++) {
//				System.out.print(arr[i][j] + " ");
//			}
//			System.out.println();
//		}
//	}

}

 

'Algorithm' 카테고리의 다른 글

백준_미세먼지안녕_17144  (0) 2020.09.06
백준_다리만들기2_17472  (0) 2020.09.04
백준_최단경로_1753  (0) 2020.09.02
백준_최소 스패닝 트리_1197  (0) 2020.09.01
SW Expert Academy_보급로  (0) 2020.08.31
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함