SlideShare una empresa de Scribd logo
1 de 39
Descargar para leer sin conexión
HI-ARC 정기모임 #6
(DFS 응용)
이재열(@kodingwarrior)
DFS (Depth First Search)
우리말로는 깊이 우선 탐색
Void DFS(int i) {
visited[i] = true;
for(auto v : graph[i])
if(!visited[v])
DFS(v); // 방문하지 않았을 경우 재귀적으로 시행
}
쉽게 말해서 먼저 보이는 지점부터 방문한다!
한번 방문한 지점은 두번 다시 확인할 필요 없도록 true 로 마킹해둔다.
DFS 가 동작하는 과정
A
B C D
E F G H
J
I
1
2
3
4
5
6
7
8
9
10
방문순서 :
A - B - E - F - C - G - J - H - D - I
DFS 를 이용한 여러가지 알고리즘
● Flood fill
● Euler circuit
● Articulation point & Bridge
● Connected Components
● Strong Connected Components
● Topological Sort
● 2-SAT problem
● …...
#1 Connected Components
그래프 이론 용어 정리
● Connected component : 어떤 길이의 path 로든 서로 도달할 수 있는 정점들로
구성된 subgraph
○ C(v) = {u ∈ V | there exists a path in G from u to v }.
관계(Relation)의 관점으로 보면 reflecxive, symmetric, transitive 모두 성립.
Equivalence class 를 나타낼 때도 쓰일 수 있음.
#1 Connected Components (1-3)
A
B
C
E
F
G
I
D
H
J
#1 Connected Components (1-3)
A
B
C
E
F
G
I
D
H
J
중간중간에 간선이 끊어져 있을 경우도
생각해야 한다.
#1 Connected Components (1-3)
A
B
C
E
F
G
I
D
H
J
#1 Connected Components
● Connected Component 는 어떻게 구할 것인가?
Undirected Graph 에서 도달할 수 있는 놈들끼리 분류한다.
● 그렇다면 어떻게 구현할 것인가?
방문한 적이 없는 각 정점마다 (더 이상 도달할 정점이 없을때까지) DFS를 수행한다.
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B C)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B C D)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B C D)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B C D E)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B C D E)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B C D E)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B C D E)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B C D E)
* Connected component는 괄호로 묶어서 표시
비슷한 과정을 거쳐서…….
#1 Connected Components
Void dfs(int u) {
visited[u] = true;
for(auto v : graph[u])
if(!visited[v])
dfs(u);
}
Int main() {
for(int i=1; i<=V; ++i)
if(!visited(i)) {
dfs(i); dfs_count++;
}
}
A
B
C
E
F
G
I
D
H
J
DFS 방문 순서 : (A B C D E) (F G) (H I J)
* Connected component는 괄호로 묶어서 표시
#1 Connected Components
DFS 가 아니더라도, Disjoint Set 자료구조를 이용하여 구현할 수도 있다!
Disjoint Set 자료구조를 이용하는 방법은 Minimum Spanning Tree 세션에서 추후 설명
Connected Components 연습문제
https://www.acmicpc.net/problem/11724
#2 Flood Fill
격자로 나타내는 묵시적 그래프에서 사용되는 알고리즘
직역하면 (웅덩이에) 흘러넘치도록 채운다!
사실상, Connected Component 랑 다를게 없는 문제
Flood Fill pseudo code
Int dx[] = {+x,0,-x,0, ...}; // 시계방향이든 반시계 방향이든 상관없음
Int dy[] = {0, +y, 0, -y, ...};
void dfs(int y, int x) { // xy 좌표 혼동하는 것때문에 은근히 많이 틀림(팀이면 특히..?)
visited[y][x] = true;
for(int i=0; i<directions; ++i) {
Int next_x = x + dx[i]; int next_y = y + dy[i];
// 경계조건 검사
if( next_x > 0 && next_x <= MAX_X
&& next_y > 0 && next_y <= MAX_Y
&& !visited[ next_y ][ next_x ] )
dfs(next_y, next_x);
}
}
Int main() {
Int height; int width;
cin >> width >> height;
for(int i=1; i<=height; ++i)
for(int j=1; j<=width; ++j)
if(!visited[i][j])
dfs(i,j), count++;
}
Flood Fill 관련 문제들
https://www.acmicpc.net/problem/2667
https://www.acmicpc.net/problem/4963 방향의 갯수가 추가된 문제
#3 Topological Sort
그래프 이론 용어 정리
● Directed Graph(Digraph)
● Digraph 에서는 간선에 방향이 있으며, 방향을 가진 간선을 Arc 라 한다.
#3 Topological Sort
Dependency 가 아예 없는 놈부터 정렬 (DFS / BFS)
#3 Topological Sort
Void TopologicalSort(int u) {
Visited[u] = true;
for(auto v : graph[u])
if(!visited[v]) TopologicalSort(v); // 여기까지만 보면 DFS 와 유사함
stack_tmp.push(u); // 순회를 끝낸 노드는 push 해준다.
}
dependency가 없는 정점을 우선순위를 두더라도
구체적으로 어느 기준으로 정렬할 지 기준이 없으면 정답은 없음
Topological sort 관련 문제들
● 단순히 순서만 출력하는 문제
https://www.acmicpc.net/problem/1766
● 비용이 추가로 들어간 문제
https://www.acmicpc.net/problem/1005
https://www.acmicpc.net/problem/1516
https://www.acmicpc.net/problem/2056
#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 에서 도달할 수 있는 놈들끼리 분류한다.
#4 Strongly Connected Components
1
6
7
5
3
2
4
#4 Strongly Connected Components
1
6
7
5
3
2
4
SCC 알고리즘을 구현하는 두가지 알고리즘
● Kosaraju algorithm
○ DFS 를 두번 돌리는 알고리즘
○ 정방향 그래프와 역방향 그래프가 같은 SCC를 가진다는 성질을 이용함
○ O(V + E)
● Tarjan algorithm
○ O(V + E)
둘 중 어떤 알고리즘을 써도 상관 없다.
#4 Strongly Connected Components
Void KosarajuSCC(int u) {
1. 정방향 그래프를 위상정렬 후 스택에 저장
(순회를 끝낸 노드를 스택에 push 하는 방식으로 DFS)
2. 스택이 빌 때까지 최상위 원소부터 하나씩 빼가면서
(방문하지 않았을 경우에만) 역방향 그래프에서 DFS를 수행
2-1. 위에서 수행하는 DFS에서 탐색되는 모든 노드를 SCC로 묶는다.
}
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
SCC를 이용하여 푸는 문제들
https://www.acmicpc.net/problem/10451 : 간단하게 SCC의 갯수 출력
https://www.acmicpc.net/problem/2150 : 출력이 까다로운 문제(SCC의 구성요소
출력)
눈치챈 사람도 있겠지만 다루지 못한 알고리즘도
있음● Euler circuit
● Articulation point & Bridge
● 2-SAT
● …
혼자 다 준비하느라, 역량도 시간도 모자란 관계로…. 내년을 기약하는 걸로 갑시다,,,,
다음 주까지 BFS, Queue 복습해오세요

Más contenido relacionado

La actualidad más candente

C++ 타입 추론
C++ 타입 추론C++ 타입 추론
C++ 타입 추론Huey Park
 
Pure Function and Rx
Pure Function and RxPure Function and Rx
Pure Function and RxHyungho Ko
 
C++20 Key Features Summary
C++20 Key Features SummaryC++20 Key Features Summary
C++20 Key Features SummaryChris Ohk
 
[C++ korea] effective modern c++ study item 17 19 신촌 study
[C++ korea] effective modern c++ study item 17 19 신촌 study[C++ korea] effective modern c++ study item 17 19 신촌 study
[C++ korea] effective modern c++ study item 17 19 신촌 studySeok-joon Yun
 
Pure Function and Honest Design
Pure Function and Honest DesignPure Function and Honest Design
Pure Function and Honest DesignHyungho Ko
 
Data Structure - 1st Study
Data Structure - 1st StudyData Structure - 1st Study
Data Structure - 1st StudyChris Ohk
 
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...Seok-joon Yun
 
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌Seok-joon Yun
 
[C++ korea] Effective Modern C++ 신촌 Study Item20,21,23
[C++ korea] Effective Modern C++ 신촌 Study Item20,21,23[C++ korea] Effective Modern C++ 신촌 Study Item20,21,23
[C++ korea] Effective Modern C++ 신촌 Study Item20,21,23Seok-joon Yun
 
[C++ korea] effective modern c++ study item 14 declare functions noexcept if ...
[C++ korea] effective modern c++ study item 14 declare functions noexcept if ...[C++ korea] effective modern c++ study item 14 declare functions noexcept if ...
[C++ korea] effective modern c++ study item 14 declare functions noexcept if ...Seok-joon Yun
 
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...Seok-joon Yun
 
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...Seok-joon Yun
 
[C++ Korea] Effective Modern C++ Study item 31-33
[C++ Korea] Effective Modern C++ Study item 31-33[C++ Korea] Effective Modern C++ Study item 31-33
[C++ Korea] Effective Modern C++ Study item 31-33Seok-joon Yun
 
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...Seok-joon Yun
 
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준Seok-joon Yun
 
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...Seok-joon Yun
 
C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2Chris Ohk
 
Finding Functional Programming
Finding Functional Programming Finding Functional Programming
Finding Functional Programming NAVER Engineering
 

La actualidad más candente (20)

C++ 타입 추론
C++ 타입 추론C++ 타입 추론
C++ 타입 추론
 
Pure Function and Rx
Pure Function and RxPure Function and Rx
Pure Function and Rx
 
C++20 Key Features Summary
C++20 Key Features SummaryC++20 Key Features Summary
C++20 Key Features Summary
 
[C++ korea] effective modern c++ study item 17 19 신촌 study
[C++ korea] effective modern c++ study item 17 19 신촌 study[C++ korea] effective modern c++ study item 17 19 신촌 study
[C++ korea] effective modern c++ study item 17 19 신촌 study
 
Pure Function and Honest Design
Pure Function and Honest DesignPure Function and Honest Design
Pure Function and Honest Design
 
Data Structure - 1st Study
Data Structure - 1st StudyData Structure - 1st Study
Data Structure - 1st Study
 
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
[C++ Korea] Effective Modern C++ mva item 7 distinguish between and {} when c...
 
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
 
[C++ korea] Effective Modern C++ 신촌 Study Item20,21,23
[C++ korea] Effective Modern C++ 신촌 Study Item20,21,23[C++ korea] Effective Modern C++ 신촌 Study Item20,21,23
[C++ korea] Effective Modern C++ 신촌 Study Item20,21,23
 
Ch08
Ch08Ch08
Ch08
 
[C++ korea] effective modern c++ study item 14 declare functions noexcept if ...
[C++ korea] effective modern c++ study item 14 declare functions noexcept if ...[C++ korea] effective modern c++ study item 14 declare functions noexcept if ...
[C++ korea] effective modern c++ study item 14 declare functions noexcept if ...
 
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
[C++ korea] Effective Modern C++ study item 19 use shared ptr for shared owne...
 
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...[C++ korea] effective modern c++ study   item 2 understanding auto type deduc...
[C++ korea] effective modern c++ study item 2 understanding auto type deduc...
 
이산치5번
이산치5번이산치5번
이산치5번
 
[C++ Korea] Effective Modern C++ Study item 31-33
[C++ Korea] Effective Modern C++ Study item 31-33[C++ Korea] Effective Modern C++ Study item 31-33
[C++ Korea] Effective Modern C++ Study item 31-33
 
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
[C++ korea] effective modern c++ study item 7 distinguish between () and {} w...
 
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
[C++ Korea] Effective Modern C++ MVA item 8 Prefer nullptr to 0 and null +윤석준
 
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
[C++ Korea] Effective Modern C++ MVA item 9 Prefer alias declarations to type...
 
C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2C++17 Key Features Summary - Ver 2
C++17 Key Features Summary - Ver 2
 
Finding Functional Programming
Finding Functional Programming Finding Functional Programming
Finding Functional Programming
 

Más de 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 TF #5 (ADVANCED DFS)
HI-ARC ACM ICPC TF #5 (ADVANCED DFS)HI-ARC ACM ICPC TF #5 (ADVANCED DFS)
HI-ARC ACM ICPC TF #5 (ADVANCED DFS)Jae-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
 
[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
 

Más de 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 TF #5 (ADVANCED DFS)
HI-ARC ACM ICPC TF #5 (ADVANCED DFS)HI-ARC ACM ICPC TF #5 (ADVANCED DFS)
HI-ARC ACM ICPC TF #5 (ADVANCED DFS)
 
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
 
[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 정기모임 #6 dfs

  • 1. HI-ARC 정기모임 #6 (DFS 응용) 이재열(@kodingwarrior)
  • 2. DFS (Depth First Search) 우리말로는 깊이 우선 탐색 Void DFS(int i) { visited[i] = true; for(auto v : graph[i]) if(!visited[v]) DFS(v); // 방문하지 않았을 경우 재귀적으로 시행 } 쉽게 말해서 먼저 보이는 지점부터 방문한다! 한번 방문한 지점은 두번 다시 확인할 필요 없도록 true 로 마킹해둔다.
  • 3. DFS 가 동작하는 과정 A B C D E F G H J I 1 2 3 4 5 6 7 8 9 10 방문순서 : A - B - E - F - C - G - J - H - D - I
  • 4. DFS 를 이용한 여러가지 알고리즘 ● Flood fill ● Euler circuit ● Articulation point & Bridge ● Connected Components ● Strong Connected Components ● Topological Sort ● 2-SAT problem ● …...
  • 5. #1 Connected Components 그래프 이론 용어 정리 ● Connected component : 어떤 길이의 path 로든 서로 도달할 수 있는 정점들로 구성된 subgraph ○ C(v) = {u ∈ V | there exists a path in G from u to v }. 관계(Relation)의 관점으로 보면 reflecxive, symmetric, transitive 모두 성립. Equivalence class 를 나타낼 때도 쓰일 수 있음.
  • 6. #1 Connected Components (1-3) A B C E F G I D H J
  • 7. #1 Connected Components (1-3) A B C E F G I D H J 중간중간에 간선이 끊어져 있을 경우도 생각해야 한다.
  • 8. #1 Connected Components (1-3) A B C E F G I D H J
  • 9. #1 Connected Components ● Connected Component 는 어떻게 구할 것인가? Undirected Graph 에서 도달할 수 있는 놈들끼리 분류한다. ● 그렇다면 어떻게 구현할 것인가? 방문한 적이 없는 각 정점마다 (더 이상 도달할 정점이 없을때까지) DFS를 수행한다.
  • 10. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A) * Connected component는 괄호로 묶어서 표시
  • 11. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B) * Connected component는 괄호로 묶어서 표시
  • 12. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B C) * Connected component는 괄호로 묶어서 표시
  • 13. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B C D) * Connected component는 괄호로 묶어서 표시
  • 14. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B C D) * Connected component는 괄호로 묶어서 표시
  • 15. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B C D E) * Connected component는 괄호로 묶어서 표시
  • 16. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B C D E) * Connected component는 괄호로 묶어서 표시
  • 17. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B C D E) * Connected component는 괄호로 묶어서 표시
  • 18. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B C D E) * Connected component는 괄호로 묶어서 표시
  • 19. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B C D E) * Connected component는 괄호로 묶어서 표시
  • 21. #1 Connected Components Void dfs(int u) { visited[u] = true; for(auto v : graph[u]) if(!visited[v]) dfs(u); } Int main() { for(int i=1; i<=V; ++i) if(!visited(i)) { dfs(i); dfs_count++; } } A B C E F G I D H J DFS 방문 순서 : (A B C D E) (F G) (H I J) * Connected component는 괄호로 묶어서 표시
  • 22. #1 Connected Components DFS 가 아니더라도, Disjoint Set 자료구조를 이용하여 구현할 수도 있다! Disjoint Set 자료구조를 이용하는 방법은 Minimum Spanning Tree 세션에서 추후 설명
  • 24. #2 Flood Fill 격자로 나타내는 묵시적 그래프에서 사용되는 알고리즘 직역하면 (웅덩이에) 흘러넘치도록 채운다! 사실상, Connected Component 랑 다를게 없는 문제
  • 25. Flood Fill pseudo code Int dx[] = {+x,0,-x,0, ...}; // 시계방향이든 반시계 방향이든 상관없음 Int dy[] = {0, +y, 0, -y, ...}; void dfs(int y, int x) { // xy 좌표 혼동하는 것때문에 은근히 많이 틀림(팀이면 특히..?) visited[y][x] = true; for(int i=0; i<directions; ++i) { Int next_x = x + dx[i]; int next_y = y + dy[i]; // 경계조건 검사 if( next_x > 0 && next_x <= MAX_X && next_y > 0 && next_y <= MAX_Y && !visited[ next_y ][ next_x ] ) dfs(next_y, next_x); } } Int main() { Int height; int width; cin >> width >> height; for(int i=1; i<=height; ++i) for(int j=1; j<=width; ++j) if(!visited[i][j]) dfs(i,j), count++; }
  • 26. Flood Fill 관련 문제들 https://www.acmicpc.net/problem/2667 https://www.acmicpc.net/problem/4963 방향의 갯수가 추가된 문제
  • 27. #3 Topological Sort 그래프 이론 용어 정리 ● Directed Graph(Digraph) ● Digraph 에서는 간선에 방향이 있으며, 방향을 가진 간선을 Arc 라 한다.
  • 28. #3 Topological Sort Dependency 가 아예 없는 놈부터 정렬 (DFS / BFS)
  • 29. #3 Topological Sort Void TopologicalSort(int u) { Visited[u] = true; for(auto v : graph[u]) if(!visited[v]) TopologicalSort(v); // 여기까지만 보면 DFS 와 유사함 stack_tmp.push(u); // 순회를 끝낸 노드는 push 해준다. } dependency가 없는 정점을 우선순위를 두더라도 구체적으로 어느 기준으로 정렬할 지 기준이 없으면 정답은 없음
  • 30. Topological sort 관련 문제들 ● 단순히 순서만 출력하는 문제 https://www.acmicpc.net/problem/1766 ● 비용이 추가로 들어간 문제 https://www.acmicpc.net/problem/1005 https://www.acmicpc.net/problem/1516 https://www.acmicpc.net/problem/2056
  • 31. #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 에서 도달할 수 있는 놈들끼리 분류한다.
  • 32. #4 Strongly Connected Components 1 6 7 5 3 2 4
  • 33. #4 Strongly Connected Components 1 6 7 5 3 2 4
  • 34. SCC 알고리즘을 구현하는 두가지 알고리즘 ● Kosaraju algorithm ○ DFS 를 두번 돌리는 알고리즘 ○ 정방향 그래프와 역방향 그래프가 같은 SCC를 가진다는 성질을 이용함 ○ O(V + E) ● Tarjan algorithm ○ O(V + E) 둘 중 어떤 알고리즘을 써도 상관 없다.
  • 35. #4 Strongly Connected Components Void KosarajuSCC(int u) { 1. 정방향 그래프를 위상정렬 후 스택에 저장 (순회를 끝낸 노드를 스택에 push 하는 방식으로 DFS) 2. 스택이 빌 때까지 최상위 원소부터 하나씩 빼가면서 (방문하지 않았을 경우에만) 역방향 그래프에서 DFS를 수행 2-1. 위에서 수행하는 DFS에서 탐색되는 모든 노드를 SCC로 묶는다. }
  • 36. 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
  • 37. SCC를 이용하여 푸는 문제들 https://www.acmicpc.net/problem/10451 : 간단하게 SCC의 갯수 출력 https://www.acmicpc.net/problem/2150 : 출력이 까다로운 문제(SCC의 구성요소 출력)
  • 38. 눈치챈 사람도 있겠지만 다루지 못한 알고리즘도 있음● Euler circuit ● Articulation point & Bridge ● 2-SAT ● … 혼자 다 준비하느라, 역량도 시간도 모자란 관계로…. 내년을 기약하는 걸로 갑시다,,,,
  • 39. 다음 주까지 BFS, Queue 복습해오세요