반응형
11438번: LCA 2
첫째 줄에 노드의 개수 N이 주어지고, 다음 N-1개 줄에는 트리 상에서 연결된 두 정점이 주어진다. 그 다음 줄에는 가장 가까운 공통 조상을 알고싶은 쌍의 개수 M이 주어지고, 다음 M개 줄에는 정
www.acmicpc.net
11437 LCA (최소 공통 조상) [Gold III]
11437번: LCA첫째 줄에 노드의 개수 N이 주어지고, 다음 N-1개 줄에는 트리 상에서 연결된 두 정점이 주어진다. 그 다음 줄에는 가장 가까운 공통 조상을 알고싶은 쌍의 개수 M이 주어지고, 다음 M개
flrjtwjrjt.tistory.com
LCA2는 LCA와 똑같은 문제지만 보다 빠른 속도를 요구하고있습니다.
이 문제를 해결하기 위해서는 최소 공통 조상을 찾는 함수의 '두 노드의 깊이를 맞추는 부분'과 '공통 조상을 찾는 부분'를 효율적으로 풀어야합니다.
속도를 줄일 수 있는 부분은 두 노드의 깊이를 맞추는 부분입니다.
점화식을 통해 부모 노드를 구하면 이를 굉장히 빠르게 해결할 수 있습니다.
// 부모 노드 점화식
parent[k][n] = parent[k - 1][ parent [k - 1][ n ] ];
// depth 차이 만큼 한번에 depth를 맞춰줌
for (int k = kmax; k >= 0; k--)
{
if (pow(2, k) <= depth[b] - depth[a]) {
if (depth[a] <= depth[parent[k][b]])
b = parent[k][b];
}
}
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
vector<vector<int>> tree;
vector<int> depth;
vector<bool> visited;
static int parent[21][100001];
static int kmax;
void BFS(int i);
int LCA(int a, int b);
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >> N;
tree.resize(N + 1);
depth.resize(N + 1);
visited.resize(N + 1);
for (int i = 0; i < N - 1; i++)
{
int a, b;
cin >> a >> b;
tree[a].push_back(b);
tree[b].push_back(a);
}
int temp = 1;
kmax = 0;
while (temp <= N) {
temp <<= 1;
kmax++;
}
BFS(1);
for (int k = 1; k <= kmax; k++) {
for (int n = 1; n <= N; n++) {
parent[k][n] = parent[k - 1][parent[k - 1][n]];
}
}
vector<int> result;
int M;
cin >> M;
for (int i = 0; i < M; i++)
{
int a, b;
cin >> a >> b;
result.push_back(LCA(a, b));
}
for (int i : result)
cout << i << "\n";
}
int LCA(int a, int b) {
if (depth[a] > depth[b]) {
int temp = a;
a = b;
b = temp;
}
for (int k = kmax; k >= 0; k--)
{
if (pow(2, k) <= depth[b] - depth[a]) {
if (depth[a] <= depth[parent[k][b]])
b = parent[k][b];
}
}
while (a != b)
{
a = parent[0][a];
b = parent[0][b];
}
return a;
}
void BFS(int i)
{
queue<pair<int, int>> q;
q.push(make_pair(i, 0));
while (q.size())
{
int curId = q.front().first;
int curLevel = q.front().second;
q.pop();
visited[curId] = true;
depth[curId] = curLevel;
for (int i : tree[curId]) {
if (visited[i])
continue;
parent[0][i] = curId;
q.push(make_pair(i, curLevel + 1));
}
}
}
반응형
LIST
'알고리즘 문제 > 백준' 카테고리의 다른 글
2775 부녀회장이 될테야 (조합론) [Bronze I] (0) | 2024.04.28 |
---|---|
11050, 11051 이항계수 구하기 (조합론) [Bronze I, Silver II] (0) | 2024.04.27 |
11437 LCA (최소 공통 조상) [Gold III] (0) | 2024.04.25 |
11505 구간 곱 구하기 (세그먼트 트리) [Gold I] (0) | 2024.04.24 |
10868 최솟값 (세그먼트 트리)[Gold I] (0) | 2024.04.23 |