Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
Tags
- DFS
- 다익스트라
- DP
- 문자열
- Backtracking
- strtok
- 백준
- 가장 긴 증가하는 부분 수열
- 알고리즘
- C++1167
- 백준 17071
- BFS
- 위상정렬
- C++1967
- 백트래킹
- 순열
- c언어
- C++ 17071
- 투포인터
- 조합론
- C++
- 인덱스 트리
- 조합
- C++ 1937
- 16933
- LIS
- 프로그래머스
- 소트 게임
- 백준 숨바꼭질5
- C++ 1918
Archives
- Today
- Total
블로그
[8일차] 그래프1 D - 11438: LCA 2 본문
728x90
플래티넘 Ⅴ
#include <iostream>
#include <vector>
#include <algorithm>
#define MAX 17
using namespace std;
int N, M;
vector<int> adjList[100001];//dfs 하려고 있는거임
bool visit[100001] = { 0, };
int depth[100001] = { 0, };
int dp[100001][MAX + 1] = { 0, };
//int node, int depth
void dfs(int n, int d) {
visit[n] = true;
depth[n] = d;
for (int i = 0; i < adjList[n].size(); i++) {
int nextNode = adjList[n][i];
if (visit[nextNode]) continue;
dp[nextNode][0] = n;
dfs(nextNode, d + 1);
}
}
//y의 depth가 더 깊다고 가정
int lca(int x, int y) {
if (depth[x] > depth[y]) swap(x, y);
//y를 x와 같은 깊이로 올려주기
for (int i = MAX; i >= 0; i--) {
//범위 안에 들어오면 y 올려주기
if (depth[y] - depth[x] >= (1 << i))
y = dp[y][i];
}
//올려주는거 끝났을 때 x랑 y가 같다면 -> x가 y의 조상인 경우
if (x == y) return x;
//MAX에서 시작해야함... 젤 높은얘 찾는거라
for (int i = MAX; i >= 0; i--) {
//(원래 엄청 큰 숫자로 하면 루트 넘어가서 둘 조상이 0으로 같음)
//x의 i번쨰 조상과 y의 i번째 조상이 다르다면
if (dp[x][i] != dp[y][i]) {
//올라가
x = dp[x][i];
y = dp[y][i];
}
}
//올라갔으면 x, y 얘네의 부모노드가 lca임
return dp[x][0];
}
int main() {
scanf("%d", &N);
int u, v;
for (int i = 1; i < N; i++) {
scanf("%d%d", &u, &v);
adjList[u].push_back(v);
adjList[v].push_back(u);
}
//1(루트)부터 시작, 루트의 depth는 1
dfs(1, 1);
//dp
for (int ith = 1; ith < MAX; ith++) {//1번쨰 조상부터.. MAX조상까지
for (int node = 1; node <= N; node++) {
//N개의 노드들에 대해서...i번째 조상까지 구한다
//depth 하나 적은 조상의 ith-1 조상이다
dp[node][ith] = dp[dp[node][ith - 1]][ith - 1] ;
}
}
scanf("%d", &M);
for (int i = 0; i < M; i++) {
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", lca(x, y));
}
}
최소공통조상 (LCA)
필요한 자료구조: depth, dp, adjList(dfs땜에), visit(dfs땜에)
풀려면 depth랑 dp가 필수로 필요한데 depth를 구하려면 dfs(또는 bfs)가 필요하다
근데 dfs하려면 adjList랑 visit이 필요하다
lca 알고리즘 자체는 for문 두 개면 된다
1. 노드 u와 v를 같은 depth로 만들어주는 for문 이랑
2. depth가 같아진 u와 v를 lca의 child로 만들어주는 for문
끝!
https://www.acmicpc.net/problem/3584
3584번: 가장 가까운 공통 조상
루트가 있는 트리(rooted tree)가 주어지고, 그 트리 상의 두 정점이 주어질 때 그들의 가장 가까운 공통 조상(Nearest Common Anscestor)은 다음과 같이 정의됩니다. 두 노드의 가장 가까운 공통 조상은, 두
www.acmicpc.net
루트가 없는 트리도 존재하나?
아니라고 할때 -> 루트를 안알려주면 찾아야겠다
-> lca 알고리즘에서는 루트로부터의 depth가 중요하다
'SDS ( -> PS)' 카테고리의 다른 글
[8일차] 그래프2 H - 1854: K번째 최단경로 찾기 (0) | 2022.01.12 |
---|---|
[7일차] 그래프2 B - 1753: 최단경로 (0) | 2022.01.11 |
[6일차] 그래프1 F - 1516: 게임 개발 (0) | 2022.01.11 |
[6일차] 그래프1 B - 2252 : 줄 세우기 (0) | 2022.01.10 |
[6일차] 그래프1 C - 1922 : 네트워크 연결 (0) | 2022.01.10 |
Comments