Hello Ocean! ๐ŸŒผ

[๋ฐฑ์ค€/C++] 11437, 11438. LCA 1,2 ๋ณธ๋ฌธ

Algorithm

[๋ฐฑ์ค€/C++] 11437, 11438. LCA 1,2

bba_dda 2021. 7. 27. 20:55
๋ฐ˜์‘ํ˜•

๋ฌธ์ œ

https://www.acmicpc.net/problem/11437  -> LCA 1

https://www.acmicpc.net/problem/11438  -> LCA 2

 

์ฃผ์–ด์ง„ ๋‘ ๋…ธ๋“œ์— ๋Œ€ํ•ด LCA(๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ)์„ ๊ตฌํ•˜๋ฉด ๋˜๋Š” ๋ฌธ์ œ์ด๋‹ค.

1๋ฒˆ๊ณผ 2๋ฒˆ์˜ ์ฐจ์ด๋Š” ๋…ธ๋“œ์˜ ์ตœ๋Œ€ ๊ฐฏ์ˆ˜ ๋ฐ ์‹œ๊ฐ„ ์ œํ•œ์˜ ์ฐจ์ด์ด๋‹ค. 

LCA2๊ฐ€ ํ›จ์”ฌ ๋นก๋นกํ•˜๋‹ค. 

 

ํ’€์ด

1. 11437 LCA1๋ฒˆ ํ’€์ด 

์—ฐ๊ฒฐ๋œ ๋‘ ๋…ธ๋“œ a,b๊ฐ€ N-1๊ฐœ์˜ ์ค„์— ๊ฑธ์ณ์„œ ์ž…๋ ฅ๋˜๋Š”๋ฐ, a,b์ค‘์— ์–ด๋–ค ๋…ธ๋“œ๊ฐ€ ๋ถ€๋ชจ๋…ธ๋“œ์ธ์ง€๋Š” ์ž…๋ ฅ ๋ฐ›์„ ๋•Œ์—๋Š” ์•Œ ์ˆ˜๊ฐ€ ์—†๋‹ค. 

๊ทธ๋ž˜์„œ ์ฒ˜์Œ์—๋Š” ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ๋กœ ์ €์žฅํ–ˆ๋‹ค๊ฐ€, ์ž…๋ ฅ์„ ๋‹ค ๋ฐ›์€ ํ›„์— BFS๋ฅผ ํ†ตํ•ด ๋ฃจํŠธ์ธ 1๋ถ€ํ„ฐ ํƒ€๊ณ  ๋“ค์–ด๊ฐ€์„œ ํŠธ๋ฆฌ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. (๊ฐ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ์™€, ๊นŠ์ด ์ €์žฅ) 

๊ทธ๋ฆฌ๊ณ  LCA๋ฅผ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์€, a,b์˜ ๊นŠ์ด๊ฐ€ ๋‹ค๋ฅด๋ฉด, ๊ฐ™์•„์งˆ ๋•Œ ๊นŒ์ง€ a,b์ค‘์— ๊นŠ์ด๊ฐ€ ๊นŠ์€ ๋…ธ๋“œ๋ฅผ ๋ถ€๋ชจ๋กœ ๊ฐฑ์‹ ์‹œํ‚ค๋ฉด์„œ ๊นŠ์ด๊ฐ€ ๊ฐ™์•„์ง€๋„๋ก ํ–ˆ๋‹ค. 

๊ทธ ํ›„์—๋Š” ๋‘ ๋…ธ๋“œ a,b๊ฐ€ ๊ฐ™์€ ๊ฐ’์ด ๋  ๋•Œ ๊นŒ์ง€, ํ•œ ๋‹จ๊ณ„์”ฉ ์œ„๋กœ ์˜ฌ๋ผ์˜ค๋ฉด์„œ ๊ฐฑ์‹ ์‹œํ‚ค๋Š” ๊ณผ์ •์„ ๊ฑฐ์ณค๋‹ค. 

 

 

2. 11438 LCA2๋ฒˆ ํ’€์ด 

1๋ฒˆ ํ’€์ด๋ฅผ ๊ทธ๋Œ€๋กœ ์ œ์ถœํ–ˆ๋”๋‹ˆ ์—ญ์‹œ ์‹œ๊ฐ„์ดˆ๊ณผ๊ฐ€ ๋‚ฌ๋‹ค!  

ํ•œ ๊ฐ€์ง€ ๋‹คํ–‰์ธ๊ฑด, ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์ง€ ์•Š๊ณ  DP๋งŒ์œผ๋กœ ํ•ด๊ฒฐ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ ์ด์—ˆ๋‹ค. 

ํŠธ๋ฆฌ์˜ ๊ตฌ์กฐ๊ฐ€ ๊ณ„์† ๋ณ€ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ์„œ DP๋ฐฉ์‹์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ๊ฐ™๋‹ค. 

parent๋ฐฐ์—ด์„ 2์ฐจ์›์œผ๋กœ ๋งŒ๋“ค์–ด์„œ, ๊ฐ ๋…ธ๋“œ๋ณ„๋กœ 2^i๋ฒˆ์งธ์˜ ๋ถ€๋ชจ๋ฅผ parent[n][i]์— ์ €์žฅํ–ˆ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  LCA๋ฅผ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์€, 1๋ฒˆ๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ 2์ฐจ์›์œผ๋กœ ๋งŒ๋“  parent๋ฅผ ์ด์šฉํ•ด์„œ ๋” ์ ์€ ์‹œ๊ฐ„๋ณต์žก๋„๋กœ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค. 

a์™€ b์˜ ๋†’์ด๋ฅผ ๊ฐ™๊ฒŒ ๋งŒ๋“ ๋‹ค์Œ์— ํ•œ ๋‹จ๊ณ„์”ฉ ์œ„๋กœ ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ ๊ณ„์‚ฐํ•˜๋Š” ๊ณผ์ •์€ 1๋ฒˆ๊ณผ ๋˜‘๊ฐ™์ง€๋งŒ, a์™€ b์˜ ๋†’์ด๋ฅผ ๊ฐ™๊ฒŒ ๋งŒ๋“ค ๋•Œ, 1๋ฒˆ์€ ํ•œ ๋‹จ๊ณ„์”ฉ ์›€์ง์ด๋Š” ๋ฐ˜๋ฉด์—, 2๋ฒˆ์€ 2๋กœ ๋‚˜๋ˆ ์„œ ๋ฐ˜์”ฉ ์˜ฌ๋ผ๊ฐ€๋ฉฐ ๊ตฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— 2๋ฒˆ์—์„œ ๊ณ„์‚ฐ ํšŸ์ˆ˜๊ฐ€ ์ค„์–ด๋“ค๊ฒŒ๋œ๋‹ค. 

 

 

์ฝ”๋“œ

1๋ฒˆ ์ฝ”๋“œ

#include <iostream>
#include <vector>
#include <queue>

#define sc scanf_s
#define maxN 50001
using namespace std;

int N, M;
vector<int> graph[maxN];
int parent[maxN];
int depth[maxN];
bool visited[maxN];

int max_depth = 0;
void BFS(int start) { //๋ถ€๋ชจ-์ž์‹ ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•จ 
	queue<int> q;
	q.push(start);
	depth[start] = 0;
	visited[start] = 1;
	while (!q.empty()) {
		int temp = q.front();
		q.pop();
		for (int i = 0;i < graph[temp].size();i++) {
			int next = graph[temp][i];
			if (!visited[next]) {
				visited[next] = 1;
				parent[next] = temp;
				depth[next] = depth[temp] + 1;
				if (depth[next] > max_depth) max_depth = depth[next];
				q.push(next);
			}
		}
	}
}
int findCommonParent(int a, int b) {
	int a_d = depth[a];
	int b_d = depth[b];

	while (true) {
		// depth๊ฐ€ ๋‹ค๋ฅธ๋ฐ ๋ถ€๋ชจ๊ฐ€ ๊ฐ™์„ ์ˆ˜๋Š” ์—†์Œ 
		if (a_d > b_d) {
			a_d--;
			a = parent[a];
		}
		else if (a_d < b_d) {
			b_d--;
			b = parent[b];
		}
		else {
			if (a == b) {
				return a;
			}
			a_d--;
			a = parent[a];
			b_d--;
			b = parent[b];
		}
	}
}
int main() {
	sc("%d", &N);
	for (int i = 1;i < N;i++) {
		int a, b;
		sc("%d %d", &a, &b);
		graph[a].push_back(b);
		graph[b].push_back(a);
	}

	// ๋ถ€๋ชจ ์ž์‹ ์ฐพ๊ธฐ 
	BFS(1);

	sc("%d", &M);
	for (int i = 0;i < M;i++) {
		int a, b;
		sc("%d %d", &a, &b);
		// ๊ณตํ†ต์กฐ์ƒ ์ฐพ์•„ ์ถœ๋ ฅ
		printf("%d\n", findCommonParent(a, b));
	}
	return 0;
}

2๋ฒˆ ์ฝ”๋“œ 

#include <iostream>
#include <vector>
#include <queue>

#define sc scanf_s
#define maxN 100001
#define maxD 18 // 10^5 < 2^17 
using namespace std;

int N, M;
vector<int> graph[maxN];
int parent[maxN][maxD]; // n์˜ 2^d๋ฒˆ ์งธ ๋ถ€๋ชจ
int depth[maxN];
bool visited[maxN];

int max_depth = 0;
void BFS(int start) { //๋ถ€๋ชจ-์ž์‹ ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•จ 
	queue<int> q;
	q.push(start);
	depth[start] = 0;
	visited[start] = 1;
	while (!q.empty()) {
		int temp = q.front();
		q.pop();
		for (int i = 0;i < graph[temp].size();i++) {
			int next = graph[temp][i];
			if (!visited[next]) {
				visited[next] = 1;
				parent[next][0] = temp;
				depth[next] = depth[temp] + 1;
				if (depth[next] > max_depth) max_depth = depth[next];
				q.push(next);
			}
		}
	}
}
int findCommonParent(int a, int b) {
	int a_d = depth[a];
	int b_d = depth[b];

	if (b_d > a_d) { // ํ•ญ์ƒ a_d >= b_d ์ด๋„๋ก 
		int temp;
		temp = a; a = b; b = temp;
		a_d = depth[a]; b_d = depth[b];
	}
	// a, b ๋†’์ด ๋งž์ถ”๊ธฐ 
	int gap = a_d - b_d; int d = 0;
	while (gap) {
		if (gap % 2 == 1) {
			a = parent[a][d];
		}
		d++;
		gap /= 2;
	}
	if (a == b) return a;
	//a์™€ b์˜ ๋ถ€๋ชจ๊ฐ€ ๊ฐ™๋„๋ก ๋งž์ถฐ์คŒ 
	// maxD๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ์ด์œ  : ๊ฐ€์žฅ "๊ฐ€๊นŒ์šด" ๊ณตํ†ต ์กฐ์ƒ์„ ๊ตฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ, 
	// j๊ฐ€ 0์ด๋ž‘ ์ตœ๋Œ€ํ•œ ๊ฐ€๊นŒ์šธ ๋•Œ๊ฐ€ ๋‹ต์ด ๋˜์–ด์•ผํ•จ 
	for (int j = maxD - 1;j >= 0;j--) { 
		if (parent[a][j] != parent[b][j]) {
			a = parent[a][j]; b = parent[b][j];
		}
	}
	
	a = parent[a][0];
	return a;
}
int main() {
	sc("%d", &N);
	for (int i = 1;i < N;i++) {
		int a, b;
		sc("%d %d", &a, &b);
		graph[a].push_back(b);
		graph[b].push_back(a);
	}

	// ํŠธ๋ฆฌ ๋งŒ๋“ค๊ธฐ 
	BFS(1);

	// DP ๊ฐ’ ์ฑ„์šฐ๊ธฐ 
	for (int i = 0;i < maxD;i++) {
		for (int j = 1;j <= N;j++) {
			int k = parent[j][i];
			if (k != 0) parent[j][i + 1] = parent[k][i];
		}
	}

	sc("%d", &M);
	for (int i = 0;i < M;i++) {
		int a, b;
		sc("%d %d", &a, &b);
		// ๊ณตํ†ต์กฐ์ƒ ์ฐพ์•„ ์ถœ๋ ฅ
		printf("%d\n", findCommonParent(a, b));
	}
	return 0;
}

๊ฒฐ๊ณผ

11437 LCA 1

11438 LCA 2

๋ฐ˜์‘ํ˜•