[백준] 11724_연결 요소의 개수

김태민·2022년 5월 3일
0

알고리즘

목록 보기
38/77

mingssssss

1. 문제

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

2. 코드

package mymain;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class BOJ_11724 {

	static boolean visited[];

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		int N = Integer.parseInt(st.nextToken());
		int M = Integer.parseInt(st.nextToken());

		int[][] map = new int[N + 1][N + 1];
		visited = new boolean[N + 1];

		for (int i = 0; i < M; i++) {
			st = new StringTokenizer(br.readLine());
			int r = Integer.parseInt(st.nextToken());
			int c = Integer.parseInt(st.nextToken());
			map[r][c] = 1;
			map[c][r] = 1;
		}

		// 입력 종료
		int answer = 0;
		for (int i = 1; i < N + 1; i++) {
			if (visited[i] == false) {
				BFS(i, N, M, map, visited);
				answer++;
			}
		}
		System.out.println(answer);

	}

	public static void BFS(int idx, int N, int M, int[][] map, boolean[] visited) {

		Queue<Integer> q = new LinkedList<>();
		q.add(idx);

		int cnt = 0;

		while (!q.isEmpty()) {

			int check = q.poll();

			for (int i = 1; i < N + 1; i++) {

				if (map[check][i] == 1 && visited[i] == false) {
					visited[i] = true;
					q.add(i);
				}
			}
		}

	}

}

3. 리뷰

bfs문제만 골라서 풀고 있는데, 다른 문제는 리스트가 만들어져 있는 문제만 풀었는데,

이 문제는 노드 간선으로 이루어진 문제라서 처음 접해보는 유형이었다.

처음에 주어진 입력만으로 푸려고 했는데 도저히 아이디어가 안 떠올라서

구글링을 해서 다른 분들의 풀이를 봤는데 이해가 가지 않았다.

혼자 끙끙거리면서 푼 경험을 살려 상세히 설명하겠다.

  1. 노드와 간선과 연결되어있는 좌표가 나오므로, 이 좌표를 인접리스트를 생성하여

    값을 넣어줬다. 무방향 그래프므로, 1 2는 2 1처럼 서로 방향성을 설정하여 넣어줬다.

    예제 1번의 경우 인접리스트는 다음과 같이 그려진다.

    0 0 0 0 0 0 0
    0 0 1 0 0 1 0
    0 1 0 0 0 1 0
    0 0 0 0 1 0 0
    0 0 0 1 0 0 1
    0 1 1 0 0 0 0
    0 0 0 0 1 0 0

  2. 인접리스트 생성 후 방문 했는지 체크하는 boolean형 배열을 생성했다.
    혼동을 피하기 위해, 들어온 좌푯값 그대로 설정했다. (1, 1)의 경우 (0, 0)에
    집어넣지 않고 그대로 (1, 1)에 넣었다.

  3. i를 1부터 N + 1까지 순회하면서 각 노드들이 연결되어있는지 확인한다.
    visited[i]가 true인 경우에는 이미 방문했으므로, false일 때만
    BFS에 i값을(행값) 넣어줘서 연결을 확인했다.

  4. Queue를 만들어서 들어온 i 값을 넣고 탐색을 시작한다.
    인접리스트의 열의 길이도 N이므로 N + 1까지 확인해서 한 열의 끝까지 확인한다.
    값을 확인했을 때 1인 경우이면서 방문하지 않은 경우, 큐에 해당 좌푯값을 넣어줬다.
    그리고 방문처리를 했다.
    그렇게 되면 (1, 2)의 경우 큐에 2가 들어가게 된다.
    그리고 그 줄에 (1, 5)의 경우에도 동일하게 5가 들어가게 된다.

    열 탐색이 끝났으므로, 큐에 들어가있는 2를 탐색한다.
    2번째 열을 쭉 탐색하면서 2와 연결되어 있는 노드를 탐색하고 큐에 집어넣는다.
    이런 탐색을 하게 되면 처음 i = 1인 값부터 1과 연결된 모든 노드를 탐색하게 된다.

    Queue가 비어있다면, 연결되어 있는 모든 노드를 탐색했으므로, 탐색을 종료하고
    answer++ 해준다.

    다음 i는 2이므로 2번째 행에 있는 모든 노드를 탐색한다... N + 1까지!

총평: 노드와 간선으로 이루어진 문제를 처음 풀어봤는데, 다른 문제도 풀 수 있을 것 같다.
오랜 시간 고민해서 그런지 완전히 내 것이 된 것 같다.

profile
어제보다 성장하는 개발자

0개의 댓글