Skip to content
CatBus
Go back

[BOJ] 바이러스 - 2606 (S3)

시간 제한메모리 제한
1 초128 MB

문제

신종 바이러스인 웜 바이러스는 네트워크를 통해 전파된다. 한 컴퓨터가 웜 바이러스에 걸리면 그 컴퓨터와 네트워크 상에서 연결되어 있는 모든 컴퓨터는 웜 바이러스에 걸리게 된다.

예를 들어 7대의 컴퓨터가 <그림 1>과 같이 네트워크 상에서 연결되어 있다고 하자. 1번 컴퓨터가 웜 바이러스에 걸리면 웜 바이러스는 2번과 5번 컴퓨터를 거쳐 3번과 6번 컴퓨터까지 전파되어 2, 3, 5, 6 네 대의 컴퓨터는 웜 바이러스에 걸리게 된다. 하지만 4번과 7번 컴퓨터는 1번 컴퓨터와 네트워크상에서 연결되어 있지 않기 때문에 영향을 받지 않는다.

어느 날 1번 컴퓨터가 웜 바이러스에 걸렸다. 컴퓨터의 수와 네트워크 상에서 서로 연결되어 있는 정보가 주어질 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어진다. 이어서 그 수만큼 한 줄에 한 쌍씩 네트워크 상에서 직접 연결되어 있는 컴퓨터의 번호 쌍이 주어진다.

출력

1번 컴퓨터가 웜 바이러스에 걸렸을 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 첫째 줄에 출력한다.

풀이

이 문제는 그래프 탐색의 기본 문제로, 1번 노드에서 시작하여 연결된 모든 노드를 찾는 문제이다.

접근 방법

1번 컴퓨터와 연결된 모든 컴퓨터를 찾는 것은 그래프에서 **연결 요소(Connected Component)**를 찾는 것과 같다. DFS 또는 BFS를 사용하여 1번 노드에서 도달 가능한 모든 노드를 찾으면 된다.

핵심 아이디어

코드

from collections import defaultdict


class Network:

    def __init__(self, N, M):
        self.N, self.M = N, M
        self.cnt = 0
        self.visited = [False] * (N + 1)
        self.visited[1] = True
        self.network = defaultdict(list)
        self._make_network()

    def _make_network(self):
        for _ in range(self.M):
            s, e = map(int, input().split())
            self.network[s].append(e)
            self.network[e].append(s)

    def search_computer(self, node=1):
        for n_node in self.network[node]:
            if self.visited[n_node]:
                continue
            self.visited[n_node] = True
            self.cnt += 1
            self.search_computer(n_node)


def main():
    N = int(input())
    M = int(input())

    network = Network(N, M)
    network.search_computer()
    print(network.cnt)


if __name__ == "__main__":
    main()

코드 설명

Network 클래스

초기화 (__init__):

self.visited = [False] * (N + 1)
self.visited[1] = True  # 1번은 이미 감염됨
self.network = defaultdict(list)

네트워크 구성 (_make_network):

def _make_network(self):
    for _ in range(self.M):
        s, e = map(int, input().split())
        self.network[s].append(e)
        self.network[e].append(s)

DFS 탐색 (search_computer):

def search_computer(self, node=1):
    for n_node in self.network[node]:
        if self.visited[n_node]:
            continue
        self.visited[n_node] = True
        self.cnt += 1
        self.search_computer(n_node)

시간 복잡도

N ≤ 100이므로 충분히 빠르게 해결할 수 있다.

다른 풀이 방법

BFS를 이용한 풀이

from collections import deque, defaultdict

N = int(input())
M = int(input())

graph = defaultdict(list)
for _ in range(M):
    s, e = map(int, input().split())
    graph[s].append(e)
    graph[e].append(s)

visited = [False] * (N + 1)
visited[1] = True

q = deque([1])
cnt = 0

while q:
    node = q.popleft()
    for n_node in graph[node]:
        if visited[n_node]:
            continue
        visited[n_node] = True
        cnt += 1
        q.append(n_node)

print(cnt)

BFS와 DFS 모두 동일한 결과를 얻을 수 있으며, 이 문제에서는 성능 차이가 거의 없다.

Union-Find를 이용한 풀이

Union-Find(Disjoint Set)를 사용하여 1번과 같은 집합에 속한 노드의 개수를 세는 방법도 가능하다.

주의 사항

  1. 1번 제외: 1번 컴퓨터는 이미 감염된 상태이므로 답에서 제외한다.
  2. 양방향 그래프: 네트워크는 양방향이므로 양쪽 모두 연결 정보를 저장한다.
  3. 방문 체크: 무한 루프를 방지하기 위해 방문 체크가 필수이다.

문제의 의의

이 문제는 그래프 탐색의 가장 기본적인 형태로, DFS/BFS의 개념을 이해하는 데 좋은 문제이다. 연결 요소를 찾는 기본 패턴을 익힐 수 있다.


Share this post:

비슷한 글

2606이 글

본문을 Xenova/multilingual-e5-small 로 임베딩하고, 그 벡터를 PCA 로 32축에 눌러 왼쪽 막대로 그렸습니다. 비슷한 글은 지문도 닮습니다 — 위아래를 견줘 보세요. 계산은 빌드 때 끝나고 벡터는 브라우저로 오지 않습니다.

Previous Post
[BOJ] 트리 - 4803 (G4)
Next Post
[Programmers] 없어진 기록 찾기 - 59042