※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 24835번 문제인 1-Trees and Queries이다.
문제는 아래 링크를 확인하자.

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

 

24835번: 1-Trees and Queries

Gildong was hiking a mountain, walking by millions of trees. Inspired by them, he suddenly came up with an interesting idea for trees in data structures: What if we add another edge in a tree? Then he found that such tree-like graphs are called 1-trees. Si

www.acmicpc.net

트리에 새 에지를 하나 추가해 얻을 수 있는 그래프를 1-Tree라고 한다. 1-Tree에는 하나의 사이클만이 존재한다는 특징이 있다.

 

새 1-Tree 위에서 경로의 길이의 홀짝별로 "한 에지를 3회 이상 지나지 않으면서" 두 점 a와 b 사이를 빠르게 이동하는 방법은 다음 세가지를 조사해보는 것으로 충분하다:

 

1. 원래의 트리에서 움직이는 경로대로 이동한다.

2. 원래의 트리 위에서 이동하듯 a에서 x로 이동한 뒤 x-y간 에지를 따라 이동하고 원래의 트리 위에서 이동하듯 y에서 b로 이동한다.

3. 원래의 트리 위에서 이동하듯 a에서 y로 이동한 뒤 y-x간 에지를 따라 이동하고 원래의 트리 위에서 이동하듯 x에서 b로 이동한다.

 

x와 y를 잇는 에지를 따라 이동하는 것은 거리 1, 그 외의 거리는 원래의 트리 위에서의 거리를 계산하는 것으로 모든 거리를 구할 수 있으므로, LCA를 이용하여 빠르게 거리를 구해 문제를 해결할 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int N;
vector<int> G[100001];

int depth[100001];
int table[20][100001];

void dfs(int cur, int par) {
	table[0][cur] = par;
	depth[cur] = depth[par] + 1;
	for (auto node : G[cur]) {
		if (node == par) continue;
		dfs(node, cur);
	}
}

void tableinit() {
	dfs(1, 0);
	for (int i = 1; i < 20; i++) {
		for (int node = 1; node <= N; node++) {
			table[i][node] = table[i - 1][table[i - 1][node]];
		}
	}
}

int dist(int x, int y) {
	int ret = 0;
	if (depth[x] < depth[y]) swap(x, y);
	int depthdiff = depth[x] - depth[y];
	int digit = 0;
	ret += depthdiff;
	while (depthdiff) {
		if (depthdiff & 1) x = table[digit][x];
		depthdiff >>= 1;
		digit++;
	}

	if (x == y) return ret;

	for (int d = 19; d > -1; d--) {
		if (table[d][x] == table[d][y]) continue;
		ret += (1 << (d + 1));
		x = table[d][x], y = table[d][y];
	}

	return ret + 2;
}

void query() {
	int x, y, a, b, k; cin >> x >> y >> a >> b >> k;
	int evendist = 1000000008, odddist = 1000000007;

	int dab = dist(a, b), dax = dist(a, x), day = dist(a, y), dbx = dist(b, x), dby = dist(b, y);
	if (dab & 1) odddist = min(odddist, dab);
	else evendist = min(evendist, dab);
	if ((dax + 1 + dby) & 1) odddist = min(odddist, (dax + 1 + dby));
	else evendist = min(evendist, (dax + 1 + dby));
	if ((day + 1 + dbx) & 1) odddist = min(odddist, (day + 1 + dbx));
	else evendist = min(evendist, (day + 1 + dbx));

	if (k & 1) {
		if (k < odddist) cout << "NO\n";
		else cout << "YES\n";
	}
	else {
		if (k < evendist) cout << "NO\n";
		else cout << "YES\n";
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> N;
	for (int i = 1; i < N; i++) {
		int x, y; cin >> x >> y;
		G[x].emplace_back(y);
		G[y].emplace_back(x);
	}

	tableinit();

	int Q; cin >> Q;
	while (Q--) {
		query();
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 24937 // C++] SciComLove (2022)  (0) 2022.04.05
[BOJ 24936 // C++] Trip Odometer  (0) 2022.04.04
[BOJ 24927 // C++] Is It Even?  (0) 2022.04.02
[BOJ 24833 // C++] Air Conditioner  (0) 2022.04.01
[BOJ 24834 // C++] Shortest and Longest LIS  (0) 2022.03.31

+ Recent posts