Hello Ocean! ๐ŸŒผ

[๋ฐฑ์ค€/C++] 10838. ํŠธ๋ฆฌ ๋ณธ๋ฌธ

Algorithm

[๋ฐฑ์ค€/C++] 10838. ํŠธ๋ฆฌ

bba_dda 2021. 7. 20. 19:50
๋ฐ˜์‘ํ˜•

๋ฌธ์ œ

https://www.acmicpc.net/problem/10838 

N๊ฐœ์˜ ๋…ธ๋“œ๋กœ ๊ตฌ์„ฑ๋œ ๋ฃจํŠธ๊ฐ€ ์žˆ๋Š” ํŠธ๋ฆฌ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฃผ์–ด์ง„๋‹ค. ๊ฐ ๋…ธ๋“œ๋Š” 0๋ถ€ํ„ฐ N-1๊นŒ์ง€์˜ ๋ฒˆํ˜ธ๋กœ ๊ตฌ๋ณ„๋˜๊ณ , 0๋ฒˆ ๋…ธ๋“œ๋Š” ๋ฃจํŠธ ๋…ธ๋“œ์ด๊ณ , ๋‚˜๋จธ์ง€ ๋…ธ๋“œ ๊ฐ๊ฐ์€ 0๋ฒˆ ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ์ด๋‹ค.

ํŠธ๋ฆฌ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์—ฐ์‚ฐ์€ ์„ธ ์ข…๋ฅ˜์ด๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ํŠธ๋ฆฌ์˜ ๋ชจ์–‘์„ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ํŠธ๋ฆฌ ์—์ง€์— ์ƒ‰์น ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ ์—ฐ์‚ฐ๊ณผ ๊ทธ ์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. 

  1. paint(a, b, c): a๋ฒˆ ๋…ธ๋“œ์™€ b๋ฒˆ ๋…ธ๋“œ๋ฅผ ์ž‡๋Š” ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์€ ํ›„, ๊ฒฝ๋กœ ์ƒ์— ์žˆ๋Š” ๋ชจ๋“  ์—์ง€๋ฅผ ์ƒ‰๊น” c๋กœ ์น ํ•œ๋‹ค. 
  2. move(a, b): a๋ฒˆ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ b๋ฒˆ ๋…ธ๋“œ๋กœ ๋ฐ”๊พผ๋‹ค. ๋‹จ, b๋ฒˆ ๋…ธ๋“œ๋Š” a๋ฒˆ ๋…ธ๋“œ๋ฅผ ๋ฃจํŠธ๋กœ ํ•˜๋Š” ๋ถ€ํŠธ๋ฆฌ(subtree)์— ์†ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ๋ฐ”๊พธ๊ธฐ ์ „ a๋ฒˆ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ p๋ผ ํ•  ๋•Œ, ์ƒˆ๋กœ์šด ์—์ง€ (a,b)๋Š” ์›๋ž˜์˜ ์—์ง€ (a,p)์˜ ์ƒ‰๊น”์„ ๊ฐ–๋Š”๋‹ค. 
  3. count(a, b): a๋ฒˆ ๋…ธ๋“œ์™€ b๋ฒˆ ๋…ธ๋“œ๋ฅผ ์ž‡๋Š” ์ตœ๋‹จ๊ฒฝ๋กœ๋ฅผ ์ฐพ์€ ํ›„, ๊ทธ ๊ฒฝ๋กœ ์‚ฌ์ด์— ์žˆ๋Š” ์—์ง€์— ์น ํ•ด์ง„ ์„œ๋กœ ๋‹ค๋ฅธ ์ƒ‰๊น”์˜ ๊ฐœ์ˆ˜๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. 

์—์ง€์— ์น ํ•˜๋Š” ์ƒ‰๊น” c๋ฅผ ์ •์ˆ˜๋กœ ํ‘œ์‹œํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฒ˜์Œ์—๋Š” ๋ชจ๋“  ์—์ง€์˜ ์ƒ‰๊น”์ด 0์ด๋ผ๊ณ  ๊ฐ€์ •ํ•œ๋‹ค. 

ํ’€์ด

paint๋ช…๋ น๊ณผ count๋ช…๋ น์—์„œ ๋…ธ๋“œ๊ฐ„ ์ตœ๋‹จ๊ฒฝ๋กœ๋ฅผ ์ฐพ์•„์•ผ ํ•œ๋‹ค. 

ํŠธ๋ฆฌ์—์„œ๋Š” ๋‘ ๋…ธ๋“œ๊ฐ„ ์ตœ๋‹จ๊ฒฝ๋กœ๋Š” ๋ฌด์กฐ๊ฑด ๋‘ ๋…ธ๋“œ์˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ ๊ฑฐ์ณ๊ฐ„๋‹ค! 

๋”ฐ๋ผ์„œ ์ง€๋‚œ๋ฒˆ์— ํ’€์—ˆ๋˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ ํ’€์ด๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. 

 

parent๋ฐฐ์—ด์— pair<int,int>(๋ถ€๋ชจ ๋…ธ๋“œ ๋ฒˆํ˜ธ, ์ƒ‰๊น”) ์„ ์ €์žฅํ•ด์„œ ์ด์šฉํ•˜์˜€๋‹ค. 

 

๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„, ์ง€๋‚œ๋ฒˆ์— ํ’€์—ˆ๋˜ ๋ฐฉ์‹์œผ๋กœ ํ–ˆ๋”๋‹ˆ ์‹œ๊ฐ„์ดˆ๊ณผ๊ฐ€ ๋‚ฌ๋‹ค! 

 

๊ฒ€์ƒ‰ํ•ด๋ณด๋‹ˆ LCS(Least Common Ancestor) ์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ๊ฝค๋‚˜ ์ •ํ˜•ํ™”๋œ? ์œ ๋ช…ํ•œ? ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด์—ˆ๋‹ค. 

์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋กœ๋„ ํ’€ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•˜๋Š”๋ฐ, ์ง€๊ธˆ์€ ์ดํ•ด๊ฐ€ ์•ˆ๋˜์–ด์„œ DP ๋น„์Šทํ•œ ๋ฐฉ์‹์„ ์ด์šฉํ–ˆ๋‹ค.

 

check๋ฐฐ์—ด์„ ์ด์šฉํ•ด์„œ, a์™€ b์‚ฌ์ด์˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์„ ์ฐพ์„ ๋•Œ, ํ•œ ๋‹จ๊ณ„์”ฉ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ ๋ฐœ๊ฒฌํ•œ ๋…ธ๋“œ๋ฅผ ์ฒดํฌ๋ฐฐ์—ด์— ํ‘œ์‹œํ•œ๋‹ค. ํ‘œ์‹œํ•˜๊ธฐ์ „์—, ์ด๋ฏธ ํ‘œ์‹œ๋œ ๋…ธ๋“œ์ด๋ฉด ๊ทธ ๋…ธ๋“œ๊ฐ€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ณตํ†ต ์กฐ์ƒ์ด ๋œ๋‹ค!  

 

check๋ฐฐ์—ด์„ bool๋กœ ํ•˜๊ณ , ๋งค๋ฒˆ ๊ณตํ†ต์กฐ์ƒ์„ ์ฐพ์„ ๋•Œ ์ดˆ๊ธฐํ™”ํ•˜๊ฒŒ ํ–ˆ๋”๋‹ˆ ์‹œ๊ฐ„์ดˆ๊ณผ๊ฐ€ ๋‚˜๋Š” ๊ฒƒ ๊ฐ™์•„์„œ, 

int๋กœ ํ•˜๊ณ  ๋งค๋ฒˆ ๊ณตํ†ต์กฐ์ƒ์„ ์ฐพ์„ ๋•Œ ๋งˆ๋‹ค ํ‘œ์‹œํ•˜๋Š” ๊ฐ’์„ ํ•˜๋‚˜์”ฉ ์ฆ๊ฐ€์‹œ์ผœ์„œ ์‚ฌ์šฉํ–ˆ๋‹ค. 

์ฝ”๋“œ

#include <iostream>
#include <vector>
#include <unordered_set>

#define sc scanf_s
using namespace std;
int N, K;
pair<int, int> parent[100001]; // <๋ถ€๋ชจ ๋…ธ๋“œ ๋ฒˆํ˜ธ, ์ƒ‰๊น”>
int check[100001];

int temp = 0;
int findCommonParent(int a, int b) {
	if (a == b) return a;
	int cnt = 0;
	temp++;
	while (cnt <= 1000) {
		if (a != 0) {
			if (check[a] == temp)
				return a;
			check[a] = temp;
			a = parent[a].first;
		}
		if (b != 0) {
			if (check[b] == temp)
				return b;
			check[b] = temp;
			b = parent[b].first;
		}
		if (a == b && a == 0) return 0;
		cnt++;
	}
}
int count(int a, int b) { 
	unordered_set<int> colors;
	int commonP = findCommonParent(a, b);
	while (a != commonP) {
		colors.insert(parent[a].second);
		a = parent[a].first;
	}
	while (b != commonP) {
		colors.insert(parent[b].second);
		b = parent[b].first;
	}
	return (int)colors.size(); 
}
void paint(int a, int b, int c) { 
	int commonP = findCommonParent(a, b);
	while (a != commonP) {
		parent[a].second = c;
		a = parent[a].first;
	}
	while (b != commonP) {
		parent[b].second = c;
		b = parent[b].first;
	}
}
void func(int op) {
	int a, b; sc("%d %d", &a, &b);
	if (op == 1) { //paint 
		int c; 
		sc("%d", &c);
		paint(a, b, c);
	}
	else if (op == 2) { // move
		parent[a].first = b; //a์˜ ๋ถ€๋ชจ๋ฅผ b๋กœ ๋ฐ”๊พผ๋‹ค! 
	}
	else { // count
		int cnts = count(a, b);
		printf("%d\n", cnts);
	}
}
int main() {
	sc("%d %d", &N, &K);
	parent[0].first = -1;
	for (int k = 0;k < K;k++) {
		// ์—ฐ์‚ฐ์˜ ์ข…๋ฅ˜ : (1, paint) (2, move) (3, count) 
		int op; 
		sc("%d", &op);
		func(op);
	}
	return 0;
}

๊ฒฐ๊ณผ

๋ฐ˜์‘ํ˜•