๐ŸŒžAlgorithm/๐Ÿ”ฅBaekjoon

[Baekjoon] 11437_LCA

๋ฟŒ์•ผ._. 2024. 2. 19. 16:10

Gold III

๋ฌธ์ œ(์ถœ์ฒ˜: https://www.acmicpc.net/problem/11437)

< LCA >

 

๋ฌธ์ œ ํ’€์ด 

 

๋ฃจํŠธ๋Š” 1๋ฒˆ์ด๋ฏ€๋กœ 1๋ฒˆ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ๊ฐ ์ •์ ๊นŒ์ง€์˜ ๊นŠ์ด์™€ ๋ถ€๋ชจ ์ •์ ์„ ๊ตฌํ•œ๋‹ค. ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ ์•Œ๊ณ  ์‹ถ์€ ์Œ์„ ์ž…๋ ฅ๋ฐ›์œผ๋ฉด ๋จผ์ € ์ •์  ๊นŠ์ด๋ฅผ ๊ฐ™์€ ๊นŠ์ด๋กœ ๋งž์ถ˜๋‹ค. ๊นŠ์ด๊ฐ€ ๊ฐ™๋‹ค๋ฉด ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ๋ถ€๋ชจ๋ฅผ ๊ตฌํ•œ๋‹ค.

 

 

 my solution (Java)

 

ver1.

๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ๋ถ€๋ชจ๋ฅผ ๊ตฌํ•  ๋•Œ ์šฐ์„ ์ˆœ์œ„ ํ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊นŠ์ด๊ฐ€ ๊นŠ์€ ๊ฒƒ ๋จผ์ € ๋ถ€๋ชจ๋ฅผ ์ฐพ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ–ˆ๋‹ค. ์ด ๊ฒฝ์šฐ 6992ms ์‹œ๊ฐ„์ด ๊ฑธ๋ ธ๋‹ค..

๋”๋ณด๊ธฐ
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main { // LCA
	static int depth[], n, parent[];
	static ArrayList<ArrayList<Integer>> arr;

	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st;

		n = Integer.parseInt(bf.readLine());

		arr = new ArrayList<>();
		depth = new int[n + 1];
		parent = new int[n + 1];

		for (int i = 0; i <= n; i++) {
			arr.add(new ArrayList<>());
		}

		for (int i = 0; i < n - 1; i++) {
			st = new StringTokenizer(bf.readLine());

			int a = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());

			arr.get(a).add(b);
			arr.get(b).add(a);
		}

		findDepth();

		int m = Integer.parseInt(bf.readLine());
		for (int i = 0; i < m; i++) {
			st = new StringTokenizer(bf.readLine());

			int a = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());

			bw.write(findParent(a, b) + "\n");
		}
		bw.flush();
	}

	private static int findParent(int a, int b) {
		PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() { // ์ •์  ๋ฒˆํ˜ธ, ๊นŠ์ด

			@Override
			public int compare(int[] o1, int[] o2) {
				return o2[1] - o1[1];
			}
		});
		queue.add(new int[] { a, depth[a], -1 });
		queue.add(new int[] { b, depth[b], -2 });

		int aParent = a;
		int bParent = b;

		while (!queue.isEmpty()) {
			if (aParent == bParent) {
				break;
			}

			int info[] = queue.poll();

			int num = parent[info[0]];
			if (info[2] == -1) {
				aParent = num;
				queue.add(new int[] { num, depth[num], -1 });
			} else {
				bParent = num;
				queue.add(new int[] { num, depth[num], -2 });
			}
		}
		return aParent;
	}

	private static void findDepth() {
		Queue<Integer> queue = new LinkedList<>();
		queue.add(1);

		boolean visited[] = new boolean[n + 1];
		visited[1] = true;

		while (!queue.isEmpty()) {
			int info = queue.poll();
			for (int i = 0; i < arr.get(info).size(); i++) {
				if (!visited[arr.get(info).get(i)]) {
					visited[arr.get(info).get(i)] = true;
					parent[arr.get(info).get(i)] = info;
					depth[arr.get(info).get(i)] = depth[info] + 1;
					queue.add(arr.get(info).get(i));
				}
			}
		}
	}
}

 

์ตœ์ข… ver.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class _11437_ { // LCA
	static int depth[], n, parent[];
	static ArrayList<ArrayList<Integer>> arr;

	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st;

		n = Integer.parseInt(bf.readLine());

		arr = new ArrayList<>();
		depth = new int[n + 1];
		parent = new int[n + 1];

		for (int i = 0; i <= n; i++) {
			arr.add(new ArrayList<>());
		}

		for (int i = 0; i < n - 1; i++) {
			st = new StringTokenizer(bf.readLine());

			int a = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());

			arr.get(a).add(b);
			arr.get(b).add(a);
		}

		findDepth();

		int m = Integer.parseInt(bf.readLine());
		for (int i = 0; i < m; i++) {
			st = new StringTokenizer(bf.readLine());

			int a = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());

			bw.write(findParent(a, b) + "\n");
		}
		bw.flush();
	}

	private static int findParent(int a, int b) {
		int aParent = a;
		int bParent = b;

		while (aParent != bParent) {
			if (depth[aParent] > depth[bParent]) {
				aParent = parent[aParent];
			} else if (depth[aParent] < depth[bParent]) {
				bParent = parent[bParent];
			} else {
				aParent = parent[aParent];
				bParent = parent[bParent];
			}
		}
		return aParent;
	}

	private static void findDepth() {
		Queue<Integer> queue = new LinkedList<>();
		queue.add(1);

		boolean visited[] = new boolean[n + 1];
		visited[1] = true;

		while (!queue.isEmpty()) {
			int info = queue.poll();
			for (int i = 0; i < arr.get(info).size(); i++) {
				int num = arr.get(info).get(i);
				if (!visited[num]) {
					visited[num] = true;
					parent[num] = info;
					depth[num] = depth[info] + 1;
					queue.add(num);
				}
			}
		}
	}
}
๋ณ€์ˆ˜)
n : ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜
arr : ๊ทธ๋ž˜ํ”„
depth : ๋…ธ๋“œ ๊นŠ์ด
parent : ๋…ธ๋“œ ๋ถ€๋ชจ
m : ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ ์•Œ๊ณ  ์‹ถ์€ ์Œ์˜ ๊ฐœ์ˆ˜

 

ํŠธ๋ฆฌ ์ƒ์— ์—ฐ๊ฒฐ๋œ ๋‘ ์ •์ ์„ ์ž…๋ ฅ๋ฐ›์•„ arr์— ์–‘๋ฐฉํ–ฅ์œผ๋กœ ์ €์žฅํ•œ๋‹ค. findDepth ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฃจํŠธ๋ถ€ํ„ฐ ๊นŠ์ด์™€, ๋ถ€๋ชจ๋ฅผ ๊ตฌํ•œ๋‹ค. ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ ์•Œ๊ณ  ์‹ถ์€ ์Œ์˜ ๊ฐœ์ˆ˜๋ฅผ ์ž…๋ ฅ๋ฐ›์€ ํ›„ ๊ทธ ์ˆ˜๋งŒํผ ์Œ์„ ์ž…๋ ฅ๋ฐ›์•„ findParent ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ ์ถœ๋ ฅํ•œ๋‹ค.

 

findDepth

queue์— ๋ฃจํŠธ ๋…ธ๋“œ 1์„ ๋„ฃ๊ณ  ์‹œ์ž‘ํ•œ๋‹ค. ๋ฐฉ๋ฌธ ๋ฐฐ์—ด๋„ ์„ ์–ธํ•˜์—ฌ ๋ฃจํŠธ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธ์ฒ˜๋ฆฌํ•œ๋‹ค.

queue๊ฐ€ ๋นŒ ๋•Œ๊นŒ์ง€ ๋‹ค์Œ ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•œ๋‹ค.

1) queue poll

2) ๊ทธ๋ž˜ํ”„๋ฅผ ํ†ตํ•ด ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ ํƒ์ƒ‰

3) ์•„์ง ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ๋…ธ๋“œ๋ผ๋ฉด ๋ฐฉ๋ฌธ ํ‘œ์‹œ ๋ฐ ๊นŠ์ด๋ฅผ [ํ˜„์žฌ ๊นŠ์ด+1]๋กœ ์ €์žฅ, ๋ถ€๋ชจ๋ฅผ [๋‹ค์Œ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ]=[ํ˜„์žฌ ๋…ธ๋“œ]๋กœ ์ €์žฅ, queue์— ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ์ €์žฅํ•œ๋‹ค.

 

findParent(๋…ธ๋“œ a, ๋…ธ๋“œ b)

a์˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ a๋กœ, b์˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ b๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค. ๋‘ ๋…ธ๋“œ์˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์ด ๊ฐ™์•„์งˆ ๋•Œ๊นŒ์ง€ ๋‹ค์Œ ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•œ๋‹ค.

1) a์˜ ๊นŠ์ด๊ฐ€ ๋” ํฌ๋‹ค๋ฉด ๊นŠ์ด๋ฅผ ๋งž์ถ”๊ธฐ ์œ„ํ•ด a์˜ ๋ถ€๋ชจ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

2) b์˜ ๊นŠ์ด๊ฐ€ ๋” ํฌ๋‹ค๋ฉด ๊นŠ์ด๋ฅผ ๋งž์ถ”๊ธฐ ์œ„ํ•ด b์˜ ๋ถ€๋ชจ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

3) a์™€ b์˜ ๊นŠ์ด๊ฐ€ ๊ฐ™๋‹ค๋ฉด ๋‘˜ ๋‹ค ๋ถ€๋ชจ๊ฐ€ ๊ฐ™์•„์งˆ ๋•Œ๊นŒ์ง€ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

a์™€ b์˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ ์ฐพ์•˜๋‹ค๋ฉด ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.