문제


https://www.acmicpc.net/problem/11266


풀이


사실 SCC (Strongly Connected Component)를 완벽히 이해하지 못한 것 같은 찜찜함이 있었는데, BCC (Biconnected Component)를 배우면서 SCC부터 제대로 정리해야겠단 생각이 들었다.

우선 단절점을 찾는 문제는 dfs tree에서 dfsn만 잘 관찰해도 풀 수 있다.

임의의 노드를 루트 노드로 잡고 dfs tree를 만들어보자.

그래프에서 어떤 노드가 단절점이 아니라는 것은, 그 노드를 제거했을 때 connected component 수가 그대로인 것과 동치이다.

그러므로 dfs tree의 루트 노드가 아닌 어떤 노드가 단절점이 아니라는 것은, 그 노드의 부모 노드와 자식 노드들이 연결되어 있어야 한다.

즉, 자식 노드들의 low 값이 그 노드의 dfsn 값보다 작아야 한다.

단 하나의 자식 노드라도 low 값이 그 노드의 dfsn 값보다 크거나 같으면, 그 노드는 단절점이 된다.

루트 노드가 단절점이 아니라면 dfs tree 상에서 자식 노드가 하나 이하여야 한다.


코드


import sys
sys.setrecursionlimit(10 ** 4)

n, m = map(int, sys.stdin.readline().split())
graph = [[] for _ in range(n + 1)]
for _ in range(m):
    a, b = map(int, sys.stdin.readline().split())
    graph[a].append(b)
    graph[b].append(a)

articulation = []
dfsn = [0] * (n + 1)


def dfs(cur, root):
    global idx
    dfsn[cur] = idx
    low = idx
    idx += 1
    num = 0
    flag = True

    for nxt in graph[cur]:
        if dfsn[nxt]:
            low = min(low, dfsn[nxt])
        
        else:
            num += 1
            child = dfs(nxt, False)
            low = min(low, child)
            if not root and flag and (dfsn[cur] <= child):
                articulation.append(cur)
                flag = False

    if root and (num > 1):
        articulation.append(cur)
    
    return low


for i in range(1, n + 1):
    if not dfsn[i]:
        idx = 1
        dfs(i, True)

print(len(articulation))
print(*sorted(articulation))

Leave a comment