백준 2606번 바이러스 JAVA
문제 설명
신종 바이러스인 웜 바이러스는 네트워크를 통해 전파된다. 한 컴퓨터가 웜 바이러스에 걸리면 그 컴퓨터와 네트워크 상에서 연결되어 있는 모든 컴퓨터는 웜 바이러스에 걸리게 된다.
예를 들어 7대의 컴퓨터가 <그림 1>과 같이 네트워크 상에서 연결되어 있다고 하자. 1번 컴퓨터가 웜 바이러스에 걸리면 웜 바이러스는 2번과 5번 컴퓨터를 거쳐 3번과 6번 컴퓨터까지 전파되어 2, 3, 5, 6 네 대의 컴퓨터는 웜 바이러스에 걸리게 된다. 하지만 4번과 7번 컴퓨터는 1번 컴퓨터와 네트워크상에서 연결되어 있지 않기 때문에 영향을 받지 않는다.
어느 날 1번 컴퓨터가 웜 바이러스에 걸렸다. 컴퓨터의 수와 네트워크 상에서 서로 연결되어 있는 정보가 주어질 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하인 양의 정수이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어진다. 이어서 그 수만큼 한 줄에 한 쌍씩 네트워크 상에서 직접 연결되어 있는 컴퓨터의 번호 쌍이 주어진다.
출력
1번 컴퓨터가 웜 바이러스에 걸렸을 때, 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수를 첫째 줄에 출력한다.
나의 문제 풀이 코드
import java.util.*;
import java.io.*;
public class bj2606 {
static boolean[] visited;
static ArrayList<Integer>[] graph;
static int count = 0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine()); // 컴퓨터의 수
int m = Integer.parseInt(br.readLine()); // 직접 연결된 컴퓨터 쌍의 수
// 그래프 초기화
graph = new ArrayList[n + 1];
for (int i = 1; i <= n; i++) {
graph[i] = new ArrayList<>();
}
// 그래프 정보 입력
for (int i = 0; i < m; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
graph[a].add(b);
graph[b].add(a); // 무방향 그래프이므로 양방향으로 추가
}
visited = new boolean[n + 1];
dfs(1); // 1번 컴퓨터부터 시작
// 1번 컴퓨터를 통해 웜 바이러스에 걸리게 되는 컴퓨터의 수 출력 (1은 제외)
System.out.println(count-1);
}
public static void dfs(int node) {
visited[node] = true;
count++;
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
dfs(neighbor);
}
}
}
}
문제 풀이 코멘트
그래프의 개념
그래프(Graph)는 현실 세계의 객체 또는 개념 간의 연결 관계를 표현하는 자료 구조입니다. 그래프는 실제로 네트워크, 도로망, 소셜 네트워크, 컴퓨터 네트워크 등 다양한 분야에서 활용됩니다. 그래프는 정점(Vertex)과 간선(Edge)의 집합으로 구성되며, 정점은 객체나 개념을 나타내고, 간선은 정점 간의 연결 관계를 나타냅니다. 그래프는 다양한 형태로 나타날 수 있으며, 실제로 많은 문제와 애플리케이션에서 활용됩니다.
정점(Vertex): 그래프를 구성하는 핵심 요소로, 객체나 개념을 나타냅니다. 정점은 종종 노드(Node)라고도 부릅니다.
간선(Edge): 정점 간의 연결 관계를 나타내며, 두 정점을 연결하는 선입니다. 간선은 방향 그래프(Directed Graph)와 무방향 그래프(Undirected Graph)로 나뉩니다.
방향 그래프(Directed Graph): 간선에 방향이 존재하여 한 정점에서 다른 정점으로의 방향성이 있는 그래프를 말합니다.
무방향 그래프(Undirected Graph): 간선에 방향이 없어 양쪽으로 연결된 그래프를 말합니다.
가중 그래프(Weighted Graph): 간선에 가중치(weight)가 부여된 그래프로, 간선을 통과하는 비용이나 거리 등을 나타낼 때 사용됩니다.
부분 그래프(Subgraph): 기존 그래프에서 일부 정점과 간선으로 이루어진 그래프를 의미합니다.
연결 그래프(Connected Graph): 모든 정점 쌍 간에 최소 하나의 경로가 존재하는 그래프를 의미합니다.
트리(Tree): 사이클이 없는 연결 그래프로, 모든 정점이 서로 연결되어 있으며, 트리에서 한 정점을 루트(root)라고 부릅니다.
이 문제에서는 무방향 그래프를 사용합니다. 각 컴퓨터는 그래프의 노드이며, 연결 정보를 통해 노드 간의 간선을 표현합니다.
문제 해결 방법
주어진 문제는 1번 컴퓨터를 시작으로 웜 바이러스에 걸리게 되는 컴퓨터의 수를 구하는 것입니다. 이것은 그래프의 연결된 구성 요소(Connected Component)를 찾는 문제로, 깊이 우선 탐색(DFS) 또는 너비 우선 탐색(BFS) 알고리즘을 활용할 수 있습니다. 이번에는 깊이 우선 탐색(DFS)을 사용하여 문제를 해결했습니다.
깊이 우선 탐색(DFS)은 그래프나 트리에서 정점을 탐색하는 알고리즘 중 하나입니다. DFS는 이름 그대로 가능한 깊숙이 들어가서 정점을 방문하며, 그래프의 모든 정점을 탐색하는 방법 중 하나입니다.
시작 정점에서 출발하여 다음 정점을 선택하고, 선택한 정점에서 다시 다음 정점을 선택하는 식으로 깊이 우선으로 탐색합니다.
더 이상 탐색할 수 있는 정점이 없으면 이전 정점으로 돌아가서 다른 경로로 탐색을 계속합니다.
정점을 방문할 때, 해당 정점이 이미 방문한 정점인지 여부를 확인하여 중복 방문을 피합니다.
스택(Stack)이나 재귀 함수를 사용하여 구현할 수 있습니다.
DFS는 그래프의 연결 여부, 경로 탐색, 사이클 검출, 특정 정점에 대한 탐색 등 다양한 그래프 문제를 해결하는 데 사용됩니다. 또한, DFS는 트리 구조에서도 사용되어 트리의 순회(Traversal)를 수행하며 원하는 정보를 찾는 데 활용됩니다.
웜 바이러스 전파 문제에서는 1번 컴퓨터부터 시작하여 연결된 모든 컴퓨터를 방문하면 됩니다.
- 그래프를 인접 리스트로 표현하기 위해 ArrayList<Integer>[] graph를 사용합니다.
- 그래프 정보를 입력받고, 무방향 그래프이므로 양방향으로 간선을 추가합니다.
- 방문 여부를 나타내는 visited 배열을 사용하여 DFS를 구현합니다. dfs 함수는 시작 노드부터 깊이 우선 탐색을 진행하며, 방문한 노드의 수를 카운트합니다.
- 1번 컴퓨터를 시작으로 DFS를 호출하여 웜 바이러스에 걸리게 되는 컴퓨터의 수를 구합니다.
- 마지막으로 구해진 수는 1번 컴퓨터를 포함한 컴퓨터의 수이기 때문에 1을 차감한 값을 출력합니다.
'공log > [P&B]' 카테고리의 다른 글
[P&B] #108 BAEKJOON 2346 (0) | 2023.10.02 |
---|---|
[P&B] #107 BAEKJOON 12789 (1) | 2023.10.02 |
[P&B] #105 BAEKJOON 9095 (0) | 2023.10.01 |
[P&B] #104 BAEKJOON 1463 (0) | 2023.10.01 |
[P&B] #103 BAEKJOON 9375 (0) | 2023.10.01 |