SlideShare a Scribd company logo
3-B 세미나
LCA
(Lowest Common Ancestor)
인하대학교 김진서
LCA(Lowest Common Ancestor)
Naive / Sparse Table
이걸 어디에 쓸까?
심화
LCA란?
LCA란?
트리에서 정의 되는 개념 입니다.
Lowest Common Ancestor(최소 공통 조상)
트리 구조에서 임의의 정점 A와 임의의 정점 B의 LCA(A,B)는 정점 A와 정점B
가 각각 자신의 조상을 따라 거슬러 올라갈 때 처음으로 공통으로 만나게 되
는 정점
LCA란?
다음과 같은 트리가 존재할 때 몇몇 정점들의 LCA를 예시로 보여드리겠습니다.
LCA란?
2번 정점과 7번 정점의 LCA는 1번 정점입니다.
LCA란?
6번 정점과 10번정점의 LCA는 2번 정점입니다.
LCA란?
4번 정점과 13번 정점의 LCA는 4번 정점입니다.
LCA는 어떻게 구할 수 있을까?
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
그렇다면 우리는 LCA를 어떻게 구할 수 있을까요?
우선 Naive하게 생각해봅시다!
어떤 두 정점의 최소공통 조상을 구하기 위해서는
결국 두 정점들의 조상을 따라 거슬러 올라가면 됩니다.
LCA는 어떻게 구할 수 있을까?
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
그렇다면 이걸 2가지 step으로 나누어서 naive하게 구현 할
수 있습니다.
1. LCA를 구하고 싶은 두 정점의 깊이를 맞춰준다.
2. 깊이를 맞춰준 두 정점의 깊이를 1씩 감소시킨다
(WHILE 두 정점이 같아질 때 까지)
이러한 두 단계의 과정을 거치면 LCA를 구해낼 수
있습니다.
LCA는 어떻게 구할 수 있을까?
예를들어 8번 정점과 14번 정점의 LCA를 구한다면
8번 정점과 14번 정점의 깊이를 맞춰주기 위하여
14번 정점을 9번 정점까지 올려줍니다.
이후 8번 정점과 9번 정점의 조상을 보면서 같은 정점이
나올 때 까지 거슬러 올라가줍니다.
이러한 동작으로 LCA(8,14)=2 라는 결과를 얻을 수 있습니다.
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
LCA는 어떻게 구할 수 있을까?
그렇다면 이런 Naive한 구현의 시간복잡도는 어떻게 될까요?
높이를 1씩 올라가는 구현 특징 덕분에 O(H)라는 시간 복잡도를
가지게 될 것입니다.
즉 최악의 경우 O(N)입니다.
이러한 시간 복잡도로 BOJ 11437 LCA 같은 문제는
해결 가능하지만 BOJ 11438 LCA2 문제는 O(N*M)으로는
해결하기 힘들어보입니다.
우리는 쿼리의 개수인 M을 줄이��건 불가능 해보이니
N을 어떻게든 줄여야 하겠군요!
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
Sparse Table
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
이제 LCA를 좀 더 빠르게 구할 수 있는 방법에 대해 생각해봅시다.
LCA를 구하기 위해 조상을 따라서 1칸씩 이동했지만
사실 굳이 한칸씩 이동할 필요가 없습니다.
내가 정점 A와 정점 B가 20칸씩 이동해도 조상이 같지
않다면 20칸을 한번에 이동해도 상관이 없는거죠.
Sparse Table
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
이러한 사실을 이용하여 효율적인 계산을 위해
Sparse Table이라는 것을 만들 것입니다.
우리는 이제 모든 정점 V에 대하여 V번 정점의 조상을
미리 계산할건데 V의 2^n번째 조상을 전부 저장할겁니다.
PAR[V][N]= V의 2^N번째 조상 을 구해주시면 됩니다.
우선 DFS를 이용하여
PAR[V][0] , DPH[V] = V의 깊이 를 계산해줍니다.
그 다음 PAR[V][N]=PAR[PAR[V][N-1]][N-1]이라는
공식을 이용하여 테이블을 채워줍니다.
Sparse Table
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
Sparse Table을 이용한 LCA
테이블을 전부 채워주고 나면 우리는 두 정점의
높이를 맞춰주는 작업과, 높이를 맞춰 준 뒤 조상으로
거슬러 올라가는 작업을 2^N씩 올라갈 수 있습니다.
예를들어 16번 정점과 3번 정점의 높이를 맞춰준다고
해봅시다.
16번 정점과 3번 정점의 깊이차이가
abs(DPH(16)-DPH(3))=5 가 나므로 16을 5만큼 올려줘야
합니다.
5=101(2) 이므로
우리는 16을 2^2 + 2^0 번 올려주면 됩니다.
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
Sparse Table을 이용한 LCA
만약 높이를 맞춘 두 정점이 14번 정점과 15번 정점이라 가정을
하고 LCA를 구해봅시다.
for(i:20~0)에서 2^i째 조상이 같지 않은 경우 두 정점을 2^i 씩
올려줍니다.
14번 정점과 15번 정점은 2^3번째 조상은 같지만 2^2번째
조상이 다르므로 2^2번째 조상으로 서로 올려줍니다.
각각 2번 정점 ,3번 정점이 되겠군요
이런식으로 반복문을 이용하여 2^n씩 올려주면 결국 for문이
끝난 뒤에는 두 정점중 한 정점의 부모가 두 정점의 LCA가
됩니다.
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
Sparse Table을 이용한 LCA
단 높이를 맞춰주었을 때 두 정점이 같다면 두 정점의 LCA는
해당 정점이 됩니다.
예를들면 6번 정점과 16번 정점의 LCA를 구할 때 높이를
맞춰주면 두 정점은 6번 정점으로 같아지게 됩니다.
이경우에 두 정점의 LCA는 6번 정점이 됩니다.
1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
Sparse Table을 이용한 LCA 1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
Sparse Table을 이용한 LCA 1
2 3 4
5 6 7
109 11
12
8
14
16
13
15
시간복잡도는 어떻게 될까요?
기존에 최악의 경우 O(N)으로 조상을 거슬러 올라가던 방식을
2의 지수승씩 거슬러 올라가기 때문에
O(logN)의 시간에 두 정점의 LCA를 구할 수 있습니다.
문제
BOJ 11439 LCA2
icpc.me/11439
그래서 ..?
이제 트리에서 두 정점의 LCA를 구할 수 있게 되었습니다.
근데 이걸 도대체 어디에 써야할까요?
몇가지 문제를 풀어보면서 LCA의 다양한 사용법에 대해 배워봅시다.
문제
BOJ 1761 정점들의 거리
icpc.me/1761
1761 정점들의 거리
정점들의 거리를 구하는 문제입니다.
기존의 최단거리 알고리즘(다익스트라,FW,SPFA 등...)들을 사용한다면 TLE를 보게 될
것으로 예상
됩니다.
만약에 간선의 가중치가 전부 1이라고 가정한 뒤 BFS를 사용하더라도 O(N*M)의 시간
복잡도라면 4억번의 연산이 예상됩니다.
하지만 LCA를 이용한다면 O(logN*M)에 문제를 해결 가능합니다.
1761 정점들의 거리
하나의 쿼리를 O(logN)에 해결이 가능하다면 O(MlogN)에 전체 문제를 해결 가능합니
다.
lca를 위한 전처리 dfs를 돌릴 때 각 정점의 루트로부터의 거리 d[x]를 같이 전처리 해줍
니다.
질의는 어떤 정점 x,y의 거리 dist(x,y)를 구해야합니다.
dist(x,y)= d[x]+d[y]-d[lca(x,y)) 로 구할 수 있습니다.
문제
BOJ 3176 도로 네트워크
icpc.me/3176
3176 도로 네트워크
주어 진 그래프가 트리라는 걸 캐치할 수 있는 단서
(N-1개의 도로,모든 도시 쌍에는 도시를 연결하는 유일한 경로 존재)
이 문제도 나이브하게 두 정점사이의 경로의 모든 도시들을 확인한다면 TLE를 피할 수
없습니다.
하지만 두 정점사이의 경로의 모든 도시들을 확인하지 않는다면 문제를 해결하기 힘들
어 보입니다..
하지만 놀랍게도 이문제는 쿼리 하나당 logN에 답을 구할 수 있습니다.
3176 도로 네트워크
lca를 구할 때 2^n의 조상을 저장한 sparse table을 만들 때
2^n의 조상말고도 두가지 테이블을 더 저장해줍니다.
x[N][M] = 정점 N의 2^M번째 조상까지의 경로 중 가장 긴 도로의 길이
y[N][M] = 정점 N의 2^M번째 조상까지의 경로 중 가장 짧은 도로의 길이
이 테이블 또한
x[N][M]= MAX(x[N][M-1],x[x[N][M-1]][M-1))
y[N][M]= MIN(y[N][M-1],y[y[N][M-1][M-1])
이라는 공식을 통해 채워줄 수 있습니다.
쿼리의 정점이 A,B로 주어진다면 A,B의 LCA를 구하면서 조상을 갱신해 나갈 때 x와 y
를 계속 비교해주며 답을 구해낼 수 있습니다.
소스코드: http://jason9319.tistory.com/95
문제
BOJ 13511 트리와 쿼리2
icpc.me/13511
13511 트리와 쿼리2
트리에서 두가지 종류의 쿼리를 처리하는 문제입니다.
1번 쿼리의 경우 두 정점 사이의 거리를 구해주면 됩니다.
2번 쿼리의 경우
2가지 경우로 나누어서 생각해 볼 수 있습니다.
dph[u] - dph[lca(u,v)) >= k-1 일 때
정점 u를 k-1번 올려주면 됩니다.
dph(u)-dph(lca(u,v)) <k-1 일 때
정점 v를 u,v의 경로에 속한 정점의 수-k 만큼 올려주면 됩니다.
13511 트리와 쿼리2
이때 u나 v를 올릴 때 sparse table을 이용하여 log의 시간에 올려주어야 TLE를 피할
수 있습니다.
소스코드:http://jason9319.tistory.com/317
LCA를 통한 경로 사이의 정점 검출
트리에서 두 정점 X,Y 사이에 정점 Z가 존재하는지 여부를 lca를 이용하여 검사 가능합
니다.
트리에서 최단 경로는 유일하기 때문에
dist[x,y]== dist[x,z]+dist[z,y)가 성립한다면 x y를 잇는 경로 사이에 정점 z가 존재합니
다.
난이도는 있지만 풀어볼만한
문제들
Codeforces Round #425 (Div. 2) D번
BOJ 1626 두 번째로 작은 스패닝 트리
BOJ 1396 크루스칼의 공
BOJ 10838 트리
BOJ 10637 minimum spanning tree
THANK YOU FOR YOUR ATTENTION

More Related Content

알고리즘 연합캠프 세미나 3-B (LCA)

  • 1. 3-B 세미나 LCA (Lowest Common Ancestor) 인하대학교 김진서
  • 2. LCA(Lowest Common Ancestor) Naive / Sparse Table 이걸 어디에 쓸까? 심화 LCA란?
  • 3. LCA란? 트리에서 정의 되는 개념 입니다. Lowest Common Ancestor(최소 공통 조상) 트리 구조에서 임의의 정점 A와 임의의 정점 B의 LCA(A,B)는 정점 A와 정점B 가 각각 자신의 조상을 따라 거슬러 올라갈 때 처음으로 공통으로 만나게 되 는 정점
  • 4. LCA란? 다음과 같은 트리가 존재할 때 몇몇 정점들의 LCA를 예시로 보여드리겠습니다.
  • 5. LCA란? 2번 정점과 7번 정점의 LCA는 1번 정점입니다.
  • 6. LCA란? 6번 정점과 10번정점의 LCA는 2번 정점입니다.
  • 7. LCA란? 4번 정점과 13번 정점의 LCA는 4번 정점입니다.
  • 8. LCA는 어떻게 구할 수 있을까? 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15 그렇다면 우리는 LCA를 어떻게 구할 수 있을까요? 우선 Naive하게 생각해봅시다! 어떤 두 정점의 최소공통 조상을 구하기 위해서는 결국 두 정점들의 조상을 따라 거슬러 올라가면 됩니다.
  • 9. LCA는 어떻게 구할 수 있을까? 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15 그렇다면 이걸 2가지 step으로 나누어서 naive하게 구현 할 수 있습니다. 1. LCA를 구하고 싶은 두 정점의 깊이를 맞춰준다. 2. 깊이를 맞춰준 두 정점의 깊이를 1씩 감소시킨다 (WHILE 두 정점이 같아질 때 까지) 이러한 두 단계의 과정을 거치면 LCA를 구해낼 수 있습니다.
  • 10. LCA는 어떻게 구할 수 있을까? 예를들어 8번 정점과 14번 정점의 LCA를 구한다면 8번 정점과 14번 정점의 깊이를 맞춰주기 위하여 14번 정점을 9번 정점까지 올려줍니다. 이후 8번 정점과 9번 정점의 조상을 보면서 같은 정점이 나올 때 까지 거슬러 올라가줍니다. 이러한 동작으로 LCA(8,14)=2 라는 결과를 얻을 수 있습니다. 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15
  • 11. LCA는 어떻게 구할 수 있을까? 그렇다면 이런 Naive한 구현의 시간복잡도는 어떻게 될까요? 높이를 1씩 올라가는 구현 특징 덕분에 O(H)라는 시간 복잡도를 가지게 될 것입니다. 즉 최악의 경우 O(N)입니다. 이러한 시간 복잡도로 BOJ 11437 LCA 같은 문제는 해결 가능하지만 BOJ 11438 LCA2 문제는 O(N*M)으로는 해결하기 힘들어보입니다. 우리는 쿼리의 개수인 M을 줄이는건 불가능 해보이니 N을 어떻게든 줄여야 하겠군요! 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15
  • 12. Sparse Table 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15 이제 LCA를 좀 더 빠르게 구할 수 있는 방법에 대해 생각해봅시다. LCA를 구하기 위해 조상을 따라서 1칸씩 이동했지만 사실 굳이 한칸씩 이동할 필요가 없습니다. 내가 정점 A와 정점 B가 20칸씩 이동해도 조상이 같지 않다면 20칸을 한번에 이동해도 상관이 없는거죠.
  • 13. Sparse Table 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15 이러한 사실을 이용하여 효율적인 계산을 위해 Sparse Table이라는 것을 만들 것입니다. 우리는 이제 모든 정점 V에 대하여 V번 정점의 조상을 미리 계산할건데 V의 2^n번째 조상을 전부 저장할겁니다. PAR[V][N]= V의 2^N번째 조상 을 구해주시면 됩니다. 우선 DFS를 이용하여 PAR[V][0] , DPH[V] = V의 깊이 를 계산해줍니다. 그 다음 PAR[V][N]=PAR[PAR[V][N-1]][N-1]이라는 공식을 이용하여 테이블을 채워줍니다.
  • 14. Sparse Table 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15
  • 15. Sparse Table을 이용한 LCA 테이블을 전부 채워주고 나면 우리는 두 정점의 높이를 맞춰주는 작업과, 높이를 맞춰 준 뒤 조상으로 거슬러 올라가는 작업을 2^N씩 올라갈 수 있습니다. 예를들어 16번 정점과 3번 정점의 높이를 맞춰준다고 해봅시다. 16번 정점과 3번 정점의 깊이차이가 abs(DPH(16)-DPH(3))=5 가 나므로 16을 5만큼 올려줘야 합니다. 5=101(2) 이므로 우리는 16을 2^2 + 2^0 번 올려주면 됩니다. 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15
  • 16. Sparse Table을 이용한 LCA 만약 높이를 맞춘 두 정점이 14번 정점과 15번 정점이라 가정을 하고 LCA를 구해봅시다. for(i:20~0)에서 2^i째 조상이 같지 않은 경우 두 정점을 2^i 씩 올려줍니다. 14번 정점과 15번 정점은 2^3번째 조상은 같지만 2^2번째 조상이 다르므로 2^2번째 조상으로 서로 올려줍니다. 각각 2번 정점 ,3번 정점이 되겠군요 이런식으로 반복문을 이용하여 2^n씩 올려주면 결국 for문이 끝난 뒤에는 두 정점중 한 정점의 부모가 두 정점의 LCA가 됩니다. 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15
  • 17. Sparse Table을 이용한 LCA 단 높이를 맞춰주었을 때 두 정점이 같다면 두 정점의 LCA는 해당 정점이 됩니다. 예를들면 6번 정점과 16번 정점의 LCA를 구할 때 높이를 맞춰주면 두 정점은 6번 정점으로 같아지게 됩니다. 이경우에 두 정점의 LCA는 6번 정점이 됩니다. 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15
  • 18. Sparse Table을 이용한 LCA 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15
  • 19. Sparse Table을 이용한 LCA 1 2 3 4 5 6 7 109 11 12 8 14 16 13 15 시간복잡도는 어떻게 될까요? 기존에 최악의 경우 O(N)으로 조상을 거슬러 올라가던 방식을 2의 지수승씩 거슬러 올라가기 때문에 O(logN)의 시간에 두 정점의 LCA를 구할 수 있습니다.
  • 21. 그래서 ..? 이제 트리에서 두 정점의 LCA를 구할 수 있게 되었습니다. 근데 이걸 도대체 어디에 써야할까요? 몇가지 문제를 풀어보면서 LCA의 다양한 사용법에 대해 배워봅시다.
  • 22. 문제 BOJ 1761 정점들의 거리 icpc.me/1761
  • 23. 1761 정점들의 거리 정점들의 거리를 구하는 문제입니다. 기존의 최단거리 알고리즘(다익스트라,FW,SPFA 등...)들을 사용한다면 TLE를 보게 될 것으로 예상 됩니다. 만약에 간선의 가중치가 전부 1이라고 가정한 뒤 BFS를 사용하더라도 O(N*M)의 시간 복잡도라면 4억번의 연산이 예상됩니다. 하지만 LCA를 이용한다면 O(logN*M)에 문제를 해결 가능합니다.
  • 24. 1761 정점들의 거리 하나의 쿼리를 O(logN)에 해결이 가능하다면 O(MlogN)에 전체 문제를 해결 가능합니 다. lca를 위한 전처리 dfs를 돌릴 때 각 정점의 루트로부터의 거리 d[x]를 같이 전처리 해줍 니다. 질의는 어떤 정점 x,y의 거리 dist(x,y)를 구해야합니다. dist(x,y)= d[x]+d[y]-d[lca(x,y)) 로 구할 수 있습니다.
  • 25. 문제 BOJ 3176 도로 네트워크 icpc.me/3176
  • 26. 3176 도로 네트워크 주어 진 그래프가 트리라는 걸 캐치할 수 있는 단서 (N-1개의 도로,모든 도시 쌍에는 도시를 연결하는 유일한 경로 존재) 이 문제도 나이브하게 두 정점사이의 경로의 모든 도시들을 확인한다면 TLE를 피할 수 없습니다. 하지만 두 정점사이의 경로의 모든 도시들을 확인하지 않는다면 문제를 해결하기 힘들 어 보입니다.. 하지만 놀랍게도 이문제는 쿼리 하나당 logN에 답을 구할 수 있습니다.
  • 27. 3176 도로 네트워크 lca를 구할 때 2^n의 조상을 저장한 sparse table을 만들 때 2^n의 조상말고도 두가지 테이블을 더 저장해줍니다. x[N][M] = 정점 N의 2^M번째 조상까지의 경로 중 가장 긴 도로의 길이 y[N][M] = 정점 N의 2^M번째 조상까지의 경로 중 가장 짧은 도로의 길이 이 테이블 또한 x[N][M]= MAX(x[N][M-1],x[x[N][M-1]][M-1)) y[N][M]= MIN(y[N][M-1],y[y[N][M-1][M-1]) 이라는 공식을 통해 채워줄 수 있습니다. 쿼리의 정점이 A,B로 주어진다면 A,B의 LCA를 구하면서 조상을 갱신해 나갈 때 x와 y 를 계속 비교해주며 답을 구해낼 수 있습니다. 소스코드: http://jason9319.tistory.com/95
  • 28. 문제 BOJ 13511 트리와 쿼리2 icpc.me/13511
  • 29. 13511 트리와 쿼리2 트리에서 두가지 종류의 쿼리를 처리하는 문제입니다. 1번 쿼리의 경우 두 정점 사이의 거리를 구해주면 됩니다. 2번 쿼리의 경우 2가지 경우로 나누어서 생각해 볼 수 있습니다. dph[u] - dph[lca(u,v)) >= k-1 일 때 정점 u를 k-1번 올려주면 됩니다. dph(u)-dph(lca(u,v)) <k-1 일 때 정점 v를 u,v의 경로에 속한 정점의 수-k 만큼 올려주면 됩니다.
  • 30. 13511 트리와 쿼리2 이때 u나 v를 올릴 때 sparse table을 이용하여 log의 시간에 올려주어야 TLE를 피할 수 있습니다. 소스코드:http://jason9319.tistory.com/317
  • 31. LCA를 통한 경로 사이의 정점 검출 트리에서 두 정점 X,Y 사이에 정점 Z가 존재하는지 여부를 lca를 이용하여 검사 가능합 니다. 트리에서 최단 경로는 유일하기 때문에 dist[x,y]== dist[x,z]+dist[z,y)가 성립한다면 x y를 잇는 경로 사이에 정점 z가 존재합니 다.
  • 32. 난이도는 있지만 풀어볼만한 문제들 Codeforces Round #425 (Div. 2) D번 BOJ 1626 두 번째로 작은 스패닝 트리 BOJ 1396 크루스칼의 공 BOJ 10838 트리 BOJ 10637 minimum spanning tree
  • 33. THANK YOU FOR YOUR ATTENTION