SlideShare a Scribd company logo
1 of 62
Download to read offline
HI-ARC ACM-ICPC TF #5
(Advanced DFS)
이재열(@kodingwarrior)
TOC
● Cycle Detection
● Articulation Point
● SCC
● 2-SAT Problem
Cycle Detection
● 사이클을 어떻게 찾을 것인가?
● 예) 순환 참조로 인해 위상정렬을 수행하기 어려운 경우
Background : DFS Spanning Tree
DFS Spanning Tree :
DFS 를 수행하면서 생성된 Spanning Tree 를 의미
1
2
4
3
5
6
DFS Spanning Tree 의 각 정점은
3 가지의 상태를 가진다.
● EXPLORED : 방문했지만 DFS 를 끝내지 않은 상태
● UNVISITED : 방문하지 않은 상태
● VISITED : 방문 후 DFS 를 끝낸 상태
Terminology : Tree Edge
DFS 를 통해 탐색 중인 간선.
EXPLORED 인 정점에서 UNVISITED 인 정점으로 향하는 간선
0
1 3
2
Terminology : Back Edge
사이클의 일부에 해당하는 간선.
EXPLORED 상태인 정점에서 EXPLORED 상태인 정점으로 향하는 간선
Terminology : Forward/Cross Edge
EXPLORED 상태인 정점에서 VISITED 상태인 정점으로 향하는 간선
DFS 수행 순서에 따라 Forward Edge/Tree Edge 가 뒤바뀔 수도 있다.
(Forward/Cross edge 여부는 상대적인 개념으로 이해하는게 좋다.)
Cycle Detection Algorithm
TL;DR
1. DFS Spanning Tree 를 생성하면서
2. Back edge 가 존재하는지 알아본다
Pseudo Code
Pseudo Code
연습문제
● https://www.acmicpc.net/problem/9466
#4 Strongly Connected Components
● C(v) = { u ∈ V | there exists a path in G from u to v and a path
in G from v to u }.
Directed Graph 에서 도달할 수 있는 놈들끼리 분류한다.
REF.
#4 Strongly Connected Components
1
6
7
5
3
2
4
REF.
#4 Strongly Connected Components
1
6
7
5
3
2
4
REF.
SCC 알고리즘을 구현하는 두가지 알고리즘
● Kosaraju algorithm
○ DFS 를 두번 돌리는 알고리즘
○ 정방향 그래프와 역방향 그래프가 같은 SCC를 가진다는 성질을 이용함
○ O(V + E)
● Tarjan algorithm
○ O(V + E)
둘 중 어떤 알고리즘을 써도 상관 없다.
REF.
#4 Strongly Connected Components
Void KosarajuSCC(int u) {
1. 정방향 그래프를 위상정렬 후 스택에 저장
(순회를 끝낸 노드를 스택에 push 하는 방식으로 DFS)
2. 스택이 빌 때까지 최상위 원소부터 하나씩 빼가면서
(방문하지 않았을 경우에만) 역방향 그래프에서 DFS를 수행
2-1. 위에서 수행하는 DFS에서 탐색되는 모든 노드를 SCC로 묶는다.
}
REF.
for(int i=1; i<=V; ++i)
if(!visited_forward[i])
dfs(i);
while(!st.empty()) {
int tmp = st.top();
st.pop();
if(!visited_backward[tmp]) {
scc.push_back(vector<int>());
dfs_rev(tmp);
scc_count++;
}
}
main
REF.
Articulation Point
단절점(Articulation Point, cut vertex)
: 그래프 G 의 정점 중에서 이를 제거했을 때,
G 가 연결되지 않도록 만드는 정점.
(즉, 정점을 제거했을 때 Connected Component 가 증가하도록 하는 정점)
Example
Example
Example
Example
Naive 한 방법(Articulation Point)
1. O(V+E) DFS 를 수행하여 원래 그래프에 대한 Connected Component 의 갯수를
구한다.
2. 각 정점 v ∈ V 에 대해
a. 정점 v 및 v 에 인접한 간선들을 절단한다.
b. O(V + E) DFS 를 수행하여 Connected Component 의 갯수가 증가하는지 확인한다.
c. 그렇다면, v 는 절단점이다. 절단하기 전의 상태로 다시 복구
Naive 한 방법
1. O(V+E) DFS 를 수행하여 원래 그래프에 대한 Connected Component 의 갯수를
구한다.
2. 각 정점 v ∈ V 에 대해
a. 정점 v 및 v 에 인접한 간선들을 절단한다.
b. O(V + E) DFS 를 수행하여 Connected Component 의 갯수가 증가하는지 확인한다.
c. 그렇다면, v 는 절단점이다. 절단하기 전의 상태로 다시 복구
O(V+E) 안에 해결되는 알고리즘도 존재한다.
Cycle Detection 을 수행하는 것과 유사하게,
O(V+E) DFS 를 수행하여 DFS Spanning Tree 를 구축하는 과정에서
단절점을 빠르고 효율적으로 찾아낼 수 있다.
Overview
● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록
○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할
● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값
0
3
1
4
2
5
Overview
● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록
○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할
● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값
0
3
1
4
2
5
Overview
● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록
○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할
● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값
0
3
1
4
2
5
Overview
● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록
○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할
● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값
0
3
1
4
2
5
DFS Spanning Tree 를 구축한 시점에서
현재 정점 u 에서 다음 정점 v 를 보았을 때
dfs_low(v) >= dfs_num(u) 성질이 성립하면
단절점이다.
Overview
● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록
○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할
● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값
0
3
1
4
2
5
DFS Spanning Tree 를 구축한 시점에서
현재 정점 u 에서 다음 정점 v 를 보았을 때
dfs_low(v) >= dfs_num(u) 성질이 성립하면
단절점이다.
예외 케이스
0
3
1
4
2
5
그렇게 따지면 루트도
단절점이 되어야 하는 것은
아닌가?
예외 케이스
0
3
1
4
2
5
그렇게 따지면 루트도
단절점이 되어야 하는 것은
아닌가?
DFS Spanning Tree 의 루트가 둘
이상의 자식을 가질 경우 단절점이 될
수 있음. 하나인 경우는 해당되지
않는다.
Bridge
단절선(Bridge)
: 그래프 G 의 간선 중에서 이를 제거했을 때,
G 가 연결되지 않도록 만드는 간선.
(즉, 정점을 제거했을 때 Connected Component 가 증가하도록 하는 간선)
● 단절점과 거의 유사
Overview
● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록
○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할
● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값
0
3
1
4
2
5
현재 정점 u 에서 다음 정점 v 를 보았을 때
dfs_low(v) > dfs_num(u) 성질이 성립하면
단절점이다.
Articulation Point & Bridge
Articulation Point & Bridge
연습문제
https://www.acmicpc.net/problem/11266
https://www.acmicpc.net/problem/11400
https://www.acmicpc.net/problem/14675
Tarjan’s SCC Algorithm
● 단절점 찾기 알고리즘을 개량한 버전
● Kosaraju 와 같이 O(V+E) 안에 수행
Overview
● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록
○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할
● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값
0 1
2
3 4
6
5
7
Overview
● dfs_num(u) : 몇 번째로 방문한 정점인지 기록하기 위한 용도
○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할
● dfs_low(u) : DFS 의 시작이 되는 정점
0 1
2
3 4
6
5
7
Overview
● dfs_num(u) : 몇 번째로 방문한 정점인지 기록하기 위한 용도
○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할
● dfs_low(u) : DFS 의 시작이 되는 정점
0 1
2
3 4
6
5
7
Tarjan’s SCC Algorithm (Simplified)
1. DFS Spanning Tree 를 구축하면서, 방문한 순서를 스택에 저장.
2. DFS Spanning Tree 를 구축해놓은 시점에서,
dfs_low(u) == dfs_num(u) 일 때,
각 SCC 의 루트에 해당되는 정점 u 를 뽑을 때까지 스택에서 pop 하여 SCC
리스트에 추가
3. 모든 정점을 모두 방문할때까지 1,2 과 같이 DFS 를 수행
SCC를 이용하여 푸는 문제들
https://www.acmicpc.net/problem/10451 : 간단하게 SCC의 갯수 출력
https://www.acmicpc.net/problem/2150 : 출력이 까다로운 문제(SCC의 구성요소
출력)
SCC + 위상정렬
https://www.acmicpc.net/problem/4196
2-CNF Satisfiability(줄여서 2-SAT)
논리 식과 논리 변수가 주어질 때,
논리식을 참으로 만들 수 있는 논리변수의 조합이 있는지를 판단하는 문제
3-CNF 는 NP 문제이지만, 2-CNF 는 O(N2
)로 해결 가능
2-SAT Problem
Implication Graph 를 구축하는 것이 핵심.
Implication :
p 이면 q 이다
⇔ if q, then q
⇔ p implies q
⇔ p => q
⇔ ~p V q
p q p => q
false false true
false true true
true false false
true true true
Background : implication
A V B
⇔ ~A => B
⇔ ~B => A
A
⇔ A ⋀ A (Tautology)
Background : implication
A V B
⇔ ~A => B
⇔ ~B => A
A
⇔ A ⋀ A
A V B
⇔ ~A => B
⇔ ~B => A
⇔ ( A V B ) ⋀ ( A V B )
⇔ ( ~A => B ) ⋀ ( ~B => A )
Implication Graph
A V B
⇔ ~A => B
⇔ ~B => A
⇔ ( A V B ) ⋀ ( A V B )
⇔ ( ~A => B ) ⋀ ( ~B => A )
A
~A
B
~B
(~A V B ) ⋀ (~B V C) ⋀ (A V C) ⋀ (C V B)
~A
~B
~C
A
B
C
어떻게 2-CNF 식이 참이 될 수 있는 것을
증명하는가?
p q p => q
false false true
false true true
true false false
true true true
p=>q 의 식을 통해
간선으로 추가한 함의 그래프에서
p 가 참이면 q 도 역시 참이어야 하고
논리변수 p와 같은 SCC 에 포함된
모든 논리식은 참 이 됨.
모든 SCC 에 포함된 논리식이 전부
참이 될 수 있다면, 2-CNF 식은 참이
된다.
P => Q ⋀ Q => R
⇔ P => R
P => Q ⋀ Q => R ⋀ R => P
⇔ P => P ⇔ ~P V P ⇔ True
P Q
R
어떻게 2-CNF 의 식이 거짓이
될 수 있는 것을 증명하는가?
p q ~p p => ~p
false false true true
false true true true
true false false false
true true false false
어떻게 2-CNF 의 식이 거짓이
될 수 있는 것을 증명하는가?
~p p p => ~p ~p => p
true false true false
true false true false
false true false true
false true false true
어떻게 2-CNF 의 식이 거짓이
될 수 있는 것을 증명하는가?
~p p p => ~p ~p => p p => ~p && ~p => p
true false true false false
true false true false false
false true false true false
false true false true false
A ⋀ ~A ⇔ False
(contradiction)
어떻게 2-CNF 의 식이 거짓이
될 수 있는 것을 증명하는가?
~p p p => ~p ~p => p p => ~p && ~p => p
true false true false false
true false true false false
false true false true false
false true false true false
A ⋀ ~A ⇔ False
(contradiction)
추이적인 닫힘(Transitive closure) 을 통해
Xi 와 ~Xi 가 같은 SCC 에서 도달할 수
있으면,
2-CNF 식이 거짓임을 증명할 수 있다.
(단, Xi ∈ {X1, X2, …, Xn} )
다시 CNF 식으로 돌아와서 살펴보자.
위의 논리식은 Tautology 를 이용하여 다른 식으로 재해석할 수 있고,
Implication graph 에서 어떤 SCC 로 각각 묶이느냐에 따라
(교환법칙/결합법칙에 따라) 논리곱을 임의의 순서로 적용할 수 있다.
논리곱의 성질에 의해, 위의 논리식이 참이 되려면
SCC 에 포함된 모든 논리식이 참이 되어야 하고,
Transitive closure 를 통해 어떤 식이라도 거짓이 된다면 위의 논리식은 거짓이 된다.
연습문제
https://www.acmicpc.net/problem/11277
https://www.acmicpc.net/problem/11278
https://www.acmicpc.net/problem/11280
https://www.acmicpc.net/problem/11281
https://www.acmicpc.net/problem/5009

More Related Content

What's hot

2. c언어의 기본
2. c언어의 기본2. c언어의 기본
2. c언어의 기본SeonMan Kim
 
3 2. if statement
3 2. if statement3 2. if statement
3 2. if statement웅식 전
 
20100434 류아침 주제2 결과보고
20100434 류아침 주제2 결과보고20100434 류아침 주제2 결과보고
20100434 류아침 주제2 결과보고Ahchim Ryu
 
[KOSSA] C++ Programming - 13th Study - exception handling
[KOSSA] C++ Programming - 13th Study - exception handling[KOSSA] C++ Programming - 13th Study - exception handling
[KOSSA] C++ Programming - 13th Study - exception handlingSeok-joon Yun
 
Javascript hoisting
Javascript hoistingJavascript hoisting
Javascript hoistingOhgyun Ahn
 
데이터베이스 정규화
데이터베이스 정규화데이터베이스 정규화
데이터베이스 정규화Hoyoung Jung
 
Data Structure - 1st Study
Data Structure - 1st StudyData Structure - 1st Study
Data Structure - 1st StudyChris Ohk
 

What's hot (11)

4. stack
4. stack4. stack
4. stack
 
2. c언어의 기본
2. c언어의 기본2. c언어의 기본
2. c언어의 기본
 
5. queue
5. queue5. queue
5. queue
 
3 2. if statement
3 2. if statement3 2. if statement
3 2. if statement
 
20100434 류아침 주제2 결과보고
20100434 류아침 주제2 결과보고20100434 류아침 주제2 결과보고
20100434 류아침 주제2 결과보고
 
[KOSSA] C++ Programming - 13th Study - exception handling
[KOSSA] C++ Programming - 13th Study - exception handling[KOSSA] C++ Programming - 13th Study - exception handling
[KOSSA] C++ Programming - 13th Study - exception handling
 
Javascript hoisting
Javascript hoistingJavascript hoisting
Javascript hoisting
 
데이터베이스 정규화
데이터베이스 정규화데이터베이스 정규화
데이터베이스 정규화
 
Data Structure - 1st Study
Data Structure - 1st StudyData Structure - 1st Study
Data Structure - 1st Study
 
Ch07
Ch07Ch07
Ch07
 
Ch08
Ch08Ch08
Ch08
 

More from Jae-yeol Lee

[PyCon KR 2023 Lightning talk day1] 개밥먹기 주도 개발
[PyCon KR 2023 Lightning talk day1] 개밥먹기 주도 개발[PyCon KR 2023 Lightning talk day1] 개밥먹기 주도 개발
[PyCon KR 2023 Lightning talk day1] 개밥먹기 주도 개발Jae-yeol Lee
 
Browser Engineering - Ch1 Summary
Browser Engineering - Ch1 SummaryBrowser Engineering - Ch1 Summary
Browser Engineering - Ch1 SummaryJae-yeol Lee
 
Backtracking [ICPC Sinchon]
Backtracking [ICPC Sinchon]Backtracking [ICPC Sinchon]
Backtracking [ICPC Sinchon]Jae-yeol Lee
 
HI-ARC Number Theory
HI-ARC Number TheoryHI-ARC Number Theory
HI-ARC Number TheoryJae-yeol Lee
 
HI-ARC PS 102 Brute Force
HI-ARC PS 102 Brute ForceHI-ARC PS 102 Brute Force
HI-ARC PS 102 Brute ForceJae-yeol Lee
 
HI-ARC PS 102 Bitmask
HI-ARC PS 102 BitmaskHI-ARC PS 102 Bitmask
HI-ARC PS 102 BitmaskJae-yeol Lee
 
HI-ARC ACM-ICPC 준비반 - KMP algorithm
HI-ARC ACM-ICPC 준비반 - KMP algorithmHI-ARC ACM-ICPC 준비반 - KMP algorithm
HI-ARC ACM-ICPC 준비반 - KMP algorithmJae-yeol Lee
 
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화Jae-yeol Lee
 
HI-ARC 정기모임 #7 BFS
HI-ARC 정기모임 #7 BFSHI-ARC 정기모임 #7 BFS
HI-ARC 정기모임 #7 BFSJae-yeol Lee
 
HI-ARC 정기모임 #6 dfs
HI-ARC 정기모임 #6 dfsHI-ARC 정기모임 #6 dfs
HI-ARC 정기모임 #6 dfsJae-yeol Lee
 
[APL OJT] REST API TEST
[APL OJT] REST API TEST[APL OJT] REST API TEST
[APL OJT] REST API TESTJae-yeol Lee
 
Embedded project presentation
Embedded project presentationEmbedded project presentation
Embedded project presentationJae-yeol Lee
 

More from Jae-yeol Lee (14)

[PyCon KR 2023 Lightning talk day1] 개밥먹기 주도 개발
[PyCon KR 2023 Lightning talk day1] 개밥먹기 주도 개발[PyCon KR 2023 Lightning talk day1] 개밥먹기 주도 개발
[PyCon KR 2023 Lightning talk day1] 개밥먹기 주도 개발
 
Browser Engineering - Ch1 Summary
Browser Engineering - Ch1 SummaryBrowser Engineering - Ch1 Summary
Browser Engineering - Ch1 Summary
 
Whats new rails 7
Whats new   rails 7Whats new   rails 7
Whats new rails 7
 
Backtracking [ICPC Sinchon]
Backtracking [ICPC Sinchon]Backtracking [ICPC Sinchon]
Backtracking [ICPC Sinchon]
 
HI-ARC Number Theory
HI-ARC Number TheoryHI-ARC Number Theory
HI-ARC Number Theory
 
HI-ARC PS 102 Brute Force
HI-ARC PS 102 Brute ForceHI-ARC PS 102 Brute Force
HI-ARC PS 102 Brute Force
 
HI-ARC PS 102 Bitmask
HI-ARC PS 102 BitmaskHI-ARC PS 102 Bitmask
HI-ARC PS 102 Bitmask
 
HI-ARC PS 101
HI-ARC PS 101HI-ARC PS 101
HI-ARC PS 101
 
HI-ARC ACM-ICPC 준비반 - KMP algorithm
HI-ARC ACM-ICPC 준비반 - KMP algorithmHI-ARC ACM-ICPC 준비반 - KMP algorithm
HI-ARC ACM-ICPC 준비반 - KMP algorithm
 
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
 
HI-ARC 정기모임 #7 BFS
HI-ARC 정기모임 #7 BFSHI-ARC 정기모임 #7 BFS
HI-ARC 정기모임 #7 BFS
 
HI-ARC 정기모임 #6 dfs
HI-ARC 정기모임 #6 dfsHI-ARC 정기모임 #6 dfs
HI-ARC 정기모임 #6 dfs
 
[APL OJT] REST API TEST
[APL OJT] REST API TEST[APL OJT] REST API TEST
[APL OJT] REST API TEST
 
Embedded project presentation
Embedded project presentationEmbedded project presentation
Embedded project presentation
 

HI-ARC ACM ICPC TF #5 (ADVANCED DFS)

  • 1. HI-ARC ACM-ICPC TF #5 (Advanced DFS) 이재열(@kodingwarrior)
  • 2. TOC ● Cycle Detection ● Articulation Point ● SCC ● 2-SAT Problem
  • 3. Cycle Detection ● 사이클을 어떻게 찾을 것인가? ● 예) 순환 참조로 인해 위상정렬을 수행하기 어려운 경우
  • 4. Background : DFS Spanning Tree DFS Spanning Tree : DFS 를 수행하면서 생성된 Spanning Tree 를 의미 1 2 4 3 5 6
  • 5. DFS Spanning Tree 의 각 정점은 3 가지의 상태를 가진다. ● EXPLORED : 방문했지만 DFS 를 끝내지 않은 상태 ● UNVISITED : 방문하지 않은 상태 ● VISITED : 방문 후 DFS 를 끝낸 상태
  • 6. Terminology : Tree Edge DFS 를 통해 탐색 중인 간선. EXPLORED 인 정점에서 UNVISITED 인 정점으로 향하는 간선 0 1 3 2
  • 7. Terminology : Back Edge 사이클의 일부에 해당하는 간선. EXPLORED 상태인 정점에서 EXPLORED 상태인 정점으로 향하는 간선
  • 8. Terminology : Forward/Cross Edge EXPLORED 상태인 정점에서 VISITED 상태인 정점으로 향하는 간선 DFS 수행 순서에 따라 Forward Edge/Tree Edge 가 뒤바뀔 수도 있다. (Forward/Cross edge 여부는 상대적인 개념으로 이해하는게 좋다.)
  • 9. Cycle Detection Algorithm TL;DR 1. DFS Spanning Tree 를 생성하면서 2. Back edge 가 존재하는지 알아본다
  • 13. #4 Strongly Connected Components ● C(v) = { u ∈ V | there exists a path in G from u to v and a path in G from v to u }. Directed Graph 에서 도달할 수 있는 놈들끼리 분류한다. REF.
  • 14. #4 Strongly Connected Components 1 6 7 5 3 2 4 REF.
  • 15. #4 Strongly Connected Components 1 6 7 5 3 2 4 REF.
  • 16. SCC 알고리즘을 구현하는 두가지 알고리즘 ● Kosaraju algorithm ○ DFS 를 두번 돌리는 알고리즘 ○ 정방향 그래프와 역방향 그래프가 같은 SCC를 가진다는 성질을 이용함 ○ O(V + E) ● Tarjan algorithm ○ O(V + E) 둘 중 어떤 알고리즘을 써도 상관 없다. REF.
  • 17. #4 Strongly Connected Components Void KosarajuSCC(int u) { 1. 정방향 그래프를 위상정렬 후 스택에 저장 (순회를 끝낸 노드를 스택에 push 하는 방식으로 DFS) 2. 스택이 빌 때까지 최상위 원소부터 하나씩 빼가면서 (방문하지 않았을 경우에만) 역방향 그래프에서 DFS를 수행 2-1. 위에서 수행하는 DFS에서 탐색되는 모든 노드를 SCC로 묶는다. } REF.
  • 18. for(int i=1; i<=V; ++i) if(!visited_forward[i]) dfs(i); while(!st.empty()) { int tmp = st.top(); st.pop(); if(!visited_backward[tmp]) { scc.push_back(vector<int>()); dfs_rev(tmp); scc_count++; } } main REF.
  • 19. Articulation Point 단절점(Articulation Point, cut vertex) : 그래프 G 의 정점 중에서 이를 제거했을 때, G 가 연결되지 않도록 만드는 정점. (즉, 정점을 제거했을 때 Connected Component 가 증가하도록 하는 정점)
  • 24. Naive 한 방법(Articulation Point) 1. O(V+E) DFS 를 수행하여 원래 그래프에 대한 Connected Component 의 갯수를 구한다. 2. 각 정점 v ∈ V 에 대해 a. 정점 v 및 v 에 인접한 간선들을 절단한다. b. O(V + E) DFS 를 수행하여 Connected Component 의 갯수가 증가하는지 확인한다. c. 그렇다면, v 는 절단점이다. 절단하기 전의 상태로 다시 복구
  • 25. Naive 한 방법 1. O(V+E) DFS 를 수행하여 원래 그래프에 대한 Connected Component 의 갯수를 구한다. 2. 각 정점 v ∈ V 에 대해 a. 정점 v 및 v 에 인접한 간선들을 절단한다. b. O(V + E) DFS 를 수행하여 Connected Component 의 갯수가 증가하는지 확인한다. c. 그렇다면, v 는 절단점이다. 절단하기 전의 상태로 다시 복구
  • 26. O(V+E) 안에 해결되는 알고리즘도 존재한다. Cycle Detection 을 수행하는 것과 유사하게, O(V+E) DFS 를 수행하여 DFS Spanning Tree 를 구축하는 과정에서 단절점을 빠르고 효율적으로 찾아낼 수 있다.
  • 27. Overview ● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록 ○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할 ● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값 0 3 1 4 2 5
  • 28. Overview ● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록 ○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할 ● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값 0 3 1 4 2 5
  • 29. Overview ● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록 ○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할 ● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값 0 3 1 4 2 5
  • 30. Overview ● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록 ○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할 ● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값 0 3 1 4 2 5 DFS Spanning Tree 를 구축한 시점에서 현재 정점 u 에서 다음 정점 v 를 보았을 때 dfs_low(v) >= dfs_num(u) 성질이 성립하면 단절점이다.
  • 31. Overview ● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록 ○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할 ● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값 0 3 1 4 2 5 DFS Spanning Tree 를 구축한 시점에서 현재 정점 u 에서 다음 정점 v 를 보았을 때 dfs_low(v) >= dfs_num(u) 성질이 성립하면 단절점이다.
  • 32. 예외 케이스 0 3 1 4 2 5 그렇게 따지면 루트도 단절점이 되어야 하는 것은 아닌가?
  • 33. 예외 케이스 0 3 1 4 2 5 그렇게 따지면 루트도 단절점이 되어야 하는 것은 아닌가? DFS Spanning Tree 의 루트가 둘 이상의 자식을 가질 경우 단절점이 될 수 있음. 하나인 경우는 해당되지 않는다.
  • 34. Bridge 단절선(Bridge) : 그래프 G 의 간선 중에서 이를 제거했을 때, G 가 연결되지 않도록 만드는 간선. (즉, 정점을 제거했을 때 Connected Component 가 증가하도록 하는 간선) ● 단절점과 거의 유사
  • 35. Overview ● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록 ○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할 ● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값 0 3 1 4 2 5 현재 정점 u 에서 다음 정점 v 를 보았을 때 dfs_low(v) > dfs_num(u) 성질이 성립하면 단절점이다.
  • 38.
  • 40. Tarjan’s SCC Algorithm ● 단절점 찾기 알고리즘을 개량한 버전 ● Kosaraju 와 같이 O(V+E) 안에 수행
  • 41. Overview ● dfs_num(u) : u를 맨 처음 방문했을 때 몇 번째 방문한 정점인지 기록 ○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할 ● dfs_low(u) : 정점 u에 대한 DFS spanning tree 에서 도달가능한 dfs_num 최솟값 0 1 2 3 4 6 5 7
  • 42. Overview ● dfs_num(u) : 몇 번째로 방문한 정점인지 기록하기 위한 용도 ○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할 ● dfs_low(u) : DFS 의 시작이 되는 정점 0 1 2 3 4 6 5 7
  • 43. Overview ● dfs_num(u) : 몇 번째로 방문한 정점인지 기록하기 위한 용도 ○ UNVISITED 를 EXPLORED, VISITED 와 구별하는 것 이상의 역할 ● dfs_low(u) : DFS 의 시작이 되는 정점 0 1 2 3 4 6 5 7
  • 44. Tarjan’s SCC Algorithm (Simplified) 1. DFS Spanning Tree 를 구축하면서, 방문한 순서를 스택에 저장. 2. DFS Spanning Tree 를 구축해놓은 시점에서, dfs_low(u) == dfs_num(u) 일 때, 각 SCC 의 루트에 해당되는 정점 u 를 뽑을 때까지 스택에서 pop 하여 SCC 리스트에 추가 3. 모든 정점을 모두 방문할때까지 1,2 과 같이 DFS 를 수행
  • 45.
  • 46.
  • 47. SCC를 이용하여 푸는 문제들 https://www.acmicpc.net/problem/10451 : 간단하게 SCC의 갯수 출력 https://www.acmicpc.net/problem/2150 : 출력이 까다로운 문제(SCC의 구성요소 출력)
  • 49. 2-CNF Satisfiability(줄여서 2-SAT) 논리 식과 논리 변수가 주어질 때, 논리식을 참으로 만들 수 있는 논리변수의 조합이 있는지를 판단하는 문제 3-CNF 는 NP 문제이지만, 2-CNF 는 O(N2 )로 해결 가능
  • 50. 2-SAT Problem Implication Graph 를 구축하는 것이 핵심. Implication : p 이면 q 이다 ⇔ if q, then q ⇔ p implies q ⇔ p => q ⇔ ~p V q p q p => q false false true false true true true false false true true true
  • 51. Background : implication A V B ⇔ ~A => B ⇔ ~B => A A ⇔ A ⋀ A (Tautology)
  • 52. Background : implication A V B ⇔ ~A => B ⇔ ~B => A A ⇔ A ⋀ A A V B ⇔ ~A => B ⇔ ~B => A ⇔ ( A V B ) ⋀ ( A V B ) ⇔ ( ~A => B ) ⋀ ( ~B => A )
  • 53. Implication Graph A V B ⇔ ~A => B ⇔ ~B => A ⇔ ( A V B ) ⋀ ( A V B ) ⇔ ( ~A => B ) ⋀ ( ~B => A ) A ~A B ~B
  • 54. (~A V B ) ⋀ (~B V C) ⋀ (A V C) ⋀ (C V B) ~A ~B ~C A B C
  • 55. 어떻게 2-CNF 식이 참이 될 수 있는 것을 증명하는가? p q p => q false false true false true true true false false true true true p=>q 의 식을 통해 간선으로 추가한 함의 그래프에서 p 가 참이면 q 도 역시 참이어야 하고 논리변수 p와 같은 SCC 에 포함된 모든 논리식은 참 이 됨. 모든 SCC 에 포함된 논리식이 전부 참이 될 수 있다면, 2-CNF 식은 참이 된다.
  • 56. P => Q ⋀ Q => R ⇔ P => R P => Q ⋀ Q => R ⋀ R => P ⇔ P => P ⇔ ~P V P ⇔ True P Q R
  • 57. 어떻게 2-CNF 의 식이 거짓이 될 수 있는 것을 증명하는가? p q ~p p => ~p false false true true false true true true true false false false true true false false
  • 58. 어떻게 2-CNF 의 식이 거짓이 될 수 있는 것을 증명하는가? ~p p p => ~p ~p => p true false true false true false true false false true false true false true false true
  • 59. 어떻게 2-CNF 의 식이 거짓이 될 수 있는 것을 증명하는가? ~p p p => ~p ~p => p p => ~p && ~p => p true false true false false true false true false false false true false true false false true false true false A ⋀ ~A ⇔ False (contradiction)
  • 60. 어떻게 2-CNF 의 식이 거짓이 될 수 있는 것을 증명하는가? ~p p p => ~p ~p => p p => ~p && ~p => p true false true false false true false true false false false true false true false false true false true false A ⋀ ~A ⇔ False (contradiction) 추이적인 닫힘(Transitive closure) 을 통해 Xi 와 ~Xi 가 같은 SCC 에서 도달할 수 있으면, 2-CNF 식이 거짓임을 증명할 수 있다. (단, Xi ∈ {X1, X2, …, Xn} )
  • 61. 다시 CNF 식으로 돌아와서 살펴보자. 위의 논리식은 Tautology 를 이용하여 다른 식으로 재해석할 수 있고, Implication graph 에서 어떤 SCC 로 각각 묶이느냐에 따라 (교환법칙/결합법칙에 따라) 논리곱을 임의의 순서로 적용할 수 있다. 논리곱의 성질에 의해, 위의 논리식이 참이 되려면 SCC 에 포함된 모든 논리식이 참이 되어야 하고, Transitive closure 를 통해 어떤 식이라도 거짓이 된다면 위의 논리식은 거짓이 된다.