DFS Tree의 성질을 이용하여 Articulation Point를 찾기
DFS Tree의 성질과 Articulation Point(단절점)의 정의를 활용하여 Graph에서 Articulation Point(단절점)를 찾아보자.
Definition of Articulation Point
단절점의 정의 : 어떤 Graph G에 속하는 vertex v에 대하여 vertex v와 vertex v와 incident한(edge의 구성요소로 v를 가지고 있는) edge를 G에서 제거했을 때, G가 disconnected 된다면 vertex v는 G의 Articulation Point가 된다,
*Definition of Connected G : G에 속하는 임의의 vertex v, w에 대하여 v에서 w가 reachable 하고 w에서 v가 reachable 하면 G는 connected 하다.
How to Find Articulation Point
> 보조정리1. DFS Tree에서 Root Node의 Child Node의 개수가 2개 이상이면 그 Root Node는 Articulation Point이다. (필요충분조건)
proof
i) -> 방향 증명
--> Contradiction(귀류법). 만약 Root Node가 Articulation Point가 아니라면 Graph G에서 Root Node를 제거한 G가 connected여야 한다. 그러나 DFS Tree에서는 Cycle이 존재하지 않으므로 (by Def of DFS Tree) 모순!ii) <- 방향 증명
--> Contradiction. Child Node의 개수가 1개 이하라면 Root Node를 제거한 Graph G가 Connected이므로 Root Node가 Articulation Point라는 가정에 모순!
보조정리2. Non-Root Node인 Graph G에 속하는 임의의 vertex v와 v의 1) Child Node가 u일 때 2) descendant u와 v의 proper Ancestor간 edge가 없으면 v는 Articulation Point. (필요충분조건)
proof
i) -> 방향 증명
Contradiction. v가 Articulation Point가 아니라면, u의 descendant를 포함하는 subtree와 v의 proper Ancestor가 Connected여야하는데 둘 사이에 edge가 없으므로 모순!ii) <- 방향 증명
Contradiction. V가 Articulation Point임에도 불구하고 v의 proper Ancestor와 v의 child node u의 descendant u사이에 edge가 존재하면 v를 뺀 G는 connected이므로 모순!
key lemma 3: leaf Node는 Aritculation Point가 될 수 없다.
proof
DFS Tree상에서 leaf Node와 incident한 backEdge가 존재하지 않을 때, leaf Node를 제거하더라도 여전히 남아있는 그래프 G는 Connected하다.
이 세가지 정리를 이용하여 그래프 G에 속하는 Vertex들이 Articulation Point인지 판단해주면 된다.
이것을 의사코드로 나타내면 다음과 같다.
### Pseudo Code
#pre[v] : v를 첫 방문한 순서
#low[v] : v의 descendant u(u=v일 수 있음)와 incident한 Back-Edge (u,w)가 존재할 경우 low[v] = min(pre[u], pre[w])로 정의
ArticulationPoint = [False for _ in range(V+1)]
counter = 1 #첫 방문 순서와 방문을 완료한 순서를 기록하기 위한 global변수
def DFS(v, parent of v, root Node)
visited[v] = True
pre[v] = low[v] = counter++
children = 0
for u in graph[v]:
if visited[u] and u != parent of v:
low[v] = min(low[v], pre[u]) #(v에서 u로의 Back-Edge가 존재할 때)
else:
DFS(u, v, root Node)
low[v] = min(low[v], low[u])
if low[u] >= low[v] and v != Root Node:
ArticulationPoint[v] = True
children += 1
if v == root Node and children > 1:
Articulation[v] = True
연관문제
BOJ 11266 : https://www.acmicpc.net/problem/11266
답안 예시
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)
def explore(graph, v, visited, r, root):
global counter
children = 0
visited[v] = True
pre[v] = counter
low[v] = counter
counter = counter + 1
for i in graph[v]:
if (visited[i]):
if (r != i): #BackEdge에 대해서만 low 갱신할 수 있도록 parent의 pre는 배제
low[v] = min(low[v], pre[i])
else:
explore(graph, i, visited, v, root)
low[v] = min(low[v], low[i])
if (low[i] >= pre[v]):
if (v != root):
cutPoint[v] = True
children += 1
if (r==0 and (children>1)):
cutPoint[v] = True
V, E = map(int, input().split())
graph = [ [] for i in range(V+1) ]
visited = [False for _ in range(V+1)]
cutPoint = [False for _ in range(V+1)]
pre = [0 for i in range(V+1)]
low = [0 for i in range(V+1)]
counter = 1
for _ in range(E):
a,b = map(int, input().split())
graph[a].append(b)
graph[b].append(a)
for i in range(1, V+1):
root = i
explore(graph, i, visited, 0, root)
ans = ''
cnt = 0
for i in range(1, V+1):
if (cutPoint[i] == True):
cnt += 1
ans += f'{i} '
print(cnt)
if cnt:
print(ans)
'알고리즘' 카테고리의 다른 글
[Algorithm] 다이나믹 프로그래밍 (Dynamic Programming) (0) | 2022.11.19 |
---|---|
[Algorithm] 방해꾼 논법 (Adversary Argument) (0) | 2022.11.17 |
[Algorithm] Upper Bound, Lower Bound와 Optimal Algorithm (0) | 2022.11.17 |
[Algorithm] How To Find SCC in Linear Time Complexity? (0) | 2022.11.15 |
[Algorithm] How to Find Binconnected Component by using Articulation Point (0) | 2022.11.15 |