백준 풀기

백준 2606번: 바이러스 with Java

삼겹살파튀 2025. 5. 4. 20:51

바이러스

 
 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 128 MB 212934 101687 67006 46.275%

문제

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

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

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

입력

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

출력

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

예제 입력 1 복사

7
6
1 2
2 3
1 5
5 2
5 6
4 7

예제 출력 1 복사

4

 

 


 

 

DFS BFS 문제 중에 그나마 쉬운... 바이러스를 풀기로 했다.

그런데... 뭐 어떻게 풀어야 해

문제 쳐다보고 있는데 문제 출처가???

예?????????? 초등부요??????????????

정말.. 

맴이 힘들다..........

 

입력 받는 건 한 줄 컴퓨터의 수 받고

그 담 한 줄 연결된 컴퓨터 쌍의 수

글고 그 담에 연결 컴퓨터 번호 쌍이 들어오네

 

출력은 1번 컴퓨터가 웜 바이러스 걸렸을 때 웜 바이러스에 걸리게 되는 컴퓨터의 수

타고타고타고 들어가면 다 바이러스에 걸린다 이 말이네

그냥 컴퓨터 다 갖다 버리면 아 ㄴ돼?? 왜 컴퓨터의 수를 구하는 거야.

 

입력부터 문제 발생.. 저 컴퓨터들을 어떤 타입으로 입력받아야 할까

 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int computerCount = Integer.parseInt(br.readLine());
        int connectCount = Integer.parseInt(br.readLine());
        List<List<Integer>> graph = new ArrayList<>();
        for (int i = 0; i <= computerCount; i++) {
            graph.add(new ArrayList<>());
        }

        for (int i = 0; i < connectCount; i++) {
            Stirng[] input = br.readLine.split(" ");
            int a = Integer.parseInt(input[0]);
            int b = Integer.parseInt(input[1]);

            graph.get(a).add(b);
            graph.get(b).add(a);
        }

        boolean visited[] = new boolean[computerCount + 1];
    	int virusComputersCount = dfs(1, graph, visited) - 1;
        
        System.out.println(virusComputersCount);
	}

    public static int dfs(int node, List<List<Integer>> graph, boolean[] visited) {
        visited[node] = true;
        int count = 1;

        for (int connected : graph.get(node)) {
            if (!visited[connected]) {
                count += dfs(connected, graph, visited);
            }
        }

        return count;
    }
}

 

열심히 짰는데...

컴파일 오류 났다;; 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int computerCount = Integer.parseInt(br.readLine());
        int connectCount = Integer.parseInt(br.readLine());

        List<List<Integer>> graph = new ArrayList<>();
        for (int i = 0; i <= computerCount; i++) {
            graph.add(new ArrayList<>());
        }

        for (int i = 0; i < connectCount; i++) {
            String[] input = br.readLine().split(" ");
            int a = Integer.parseInt(input[0]);
            int b = Integer.parseInt(input[1]);

            graph.get(a).add(b);
            graph.get(b).add(a);
        }

        boolean visited[] = new boolean[computerCount + 1];
    	int virusComputersCount = dfs(1, graph, visited) - 1;
        
        System.out.println(virusComputersCount);
	}

    public static int dfs(int node, List<List<Integer>> graph, boolean[] visited) {
        visited[node] = true;
        int count = 1;

        for (int connected : graph.get(node)) {
            if (!visited[connected]) {
                count += dfs(connected, graph, visited);
            }
        }

        return count;
    }
}

 

오타랑.. 빠진 import문 추가 괄호도 추가ㅎ.. 역시 IDE 있없은 큰 차이다...

 

 

통과~

DFS BFS는 뭔가 알 것 같은데 막상 쌩으로 코드 짜려면 잘 모르겠다..

일단 코드에 주석 좀 달아보겠음

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int computerCount = Integer.parseInt(br.readLine());    // 컴퓨터 수
        int connectCount = Integer.parseInt(br.readLine());    // 연결 쌍 수

        List<List<Integer>> graph = new ArrayList<>();    // 이중 리스트를 사용한 그래프 초기화 (컴퓨터 번호는 1번부터 시작하므로 0번은 더미로 추가)
        for (int i = 0; i <= computerCount; i++) {
            graph.add(new ArrayList<>());
        }
    
        // 연결 정보 입력받아서 양방향 그래프 구성
        for (int i = 0; i < connectCount; i++) {
            String[] input = br.readLine().split(" ");
            int a = Integer.parseInt(input[0]);
            int b = Integer.parseInt(input[1]);

            graph.get(a).add(b);
            graph.get(b).add(a);
        }   

        boolean visited[] = new boolean[computerCount + 1];    // 방문 여부 배열 초기화(1부터 쓸 거기 때문에 사이즈 때문에 1 더함)
    	int virusComputersCount = dfs(1, graph, visited) - 1;    // 1번 노드부터 시작하니까 1 넣고 시작. 1번 노드 제외해야 하니까 1 빼줌 
        
        System.out.println(virusComputersCount);    // 출력
	}

    public static int dfs(int node, List<List<Integer>> graph, boolean[] visited) {
        visited[node] = true;    // 방문했으니까 true로 바꿈
        int count = 1;    // 현재 노드 감염 수. 자기 자신 1에서 시작하니까

        // 연결된 컴퓨터 중 아직 방문 안 한 컴퓨터만 방문
        for (int connected : graph.get(node)) {
            if (!visited[connected]) {
                count += dfs(connected, graph, visited);
            }    // 연결된 컴퓨터 재귀로 방문해서 count에 더해주기
        }

        return count;    // 총 감염 수 return
    }
}

 

 

📌 인접 리스트란?

각 정점(컴퓨터)이 어떤 정점들과 연결되어 있는지를 리스트로 표현한 것.

예를 들어, 컴퓨터가 4대 있고 다음과 같이 연결되어 있다고 해보죠:

  • 1 - 2
  • 2 - 3
  • 1 - 4

이 문제는 인접 리스트였다... 코드 달다가 찾아봤다. 이런 문제는 뭐라고 하는지.

글고 도저히 입력을 어떻게 받아야 할 지 모르겠어서 찾아보다가 2차원 리스트로 입력을 받으면 된다는 걸 찾았다. 

 

 

✅ 2차원 리스트란?

간단히 말하면,
리스트 안에 또 다른 리스트들이 들어 있는 자료구조이다.

 

List<List<Integer>> list2D = new ArrayList<>();

// 0행
list2D.add(new ArrayList<>());
list2D.get(0).add(1);
list2D.get(0).add(2);

// 1행
list2D.add(new ArrayList<>());
list2D.get(1).add(3);
list2D.get(1).add(4);

 

이렇게 코드를 짰다고 했을 때,

 

[
  [1, 2],  // 0번째 행
  [3, 4]   // 1번째 행
]

 

이런 구조가 되는 거다!! 2차원 배열 생각하면 더 쉬울 수도..??

 

int a = list2D.get(0).get(1); // 0번째 행의 1번째 값 → 2
int b = list2D.get(1).get(0); // 1번째 행의 0번째 값 → 3

 

값은 요렇게 가져온다.

 

for (int i = 0; i < list2D.size(); i++) {
    for (int j = 0; j < list2D.get(i).size(); j++) {
        System.out.print(list2D.get(i).get(j) + " ");
    }
    System.out.println();
}

 

순회할 때는 이렇게!

 

배열은 사이즈가 고정되는 반면, 리스트는 동적이라서 추가, 변경에 용이하다.

그렇다면 메모리는? 배열이 더 적게 쓴다고 한다.

 

항목 배열 리스트
크기 조절 ❌ 불가능 ✅ 가능
인덱스로 접근 ✅ 빠름 ✅ 빠름
유연성 ❌ 낮음 ✅ 높음
선언 문법 단순 약간 복잡
2차원 구조 int[][] List<List<Integer>>

 

✅ 언제 배열, 언제 리스트?

크기가 고정됨 ➡️ 배열 (int[], int[][])
크기 변경 가능해야 함 ➡️ 리스트 (ArrayList)
속도 최우선 ➡️ 배열
연결 정보/그래프 구조/유연성 필요 ➡️ 리스트

 

상황에 맞게 잘 사용해보도록 하자.

웬만하면 리스트 쓸 듯...?? 그렇게 속도 제한이 빡빡하지 않으면...