[BOJ] 4803. 트리

Hyodong Lee·2022년 2월 15일
0

알고리즘

목록 보기
8/32

[작성일]

  • 2022-02-15

[분류]

  • dfs
  • 트리


[문제링크]

[요구사항]

  • 트리가 몇 개 있는지 구하라.


[풀이]

트리의 중요한 조건 중 하나는 cycle이 있는지 여부이다. 우선 그래프 조건을 만족하기 때문에 cycle이 생기는지만 검사하면 된다. cycle이 생기는지 여부는 바로 앞 node를 제외하고 다음 이동할 노드가 이미 방문한 곳이라면 cycle이 생기는 것이기 때문에 dfs로 쉽게 해결할 수 있다.



[코드]

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

public class Main {
    static int N, M;
    static ArrayList<Integer>[] list;
    static boolean[] visited;
    static int cnt, step = 0;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        StringBuilder resSb = new StringBuilder();

        while (true) {
            cnt = 0;
            step++;

            st = new StringTokenizer(br.readLine());
            N = Integer.parseInt(st.nextToken());
            M = Integer.parseInt(st.nextToken());

            if (N == 0 && M == 0) {
                System.out.println(resSb);
                return;
            }

            // graph 생성
            list = new ArrayList[N + 1];
            visited = new boolean[N + 1];
            for (int i = 1; i <= N; i++) {
                list[i] = new ArrayList<>();
            }

            // graph 입력받기
            int a, b;
            for (int i = 0; i < M; i++) {
                st = new StringTokenizer(br.readLine());
                a = Integer.parseInt(st.nextToken());
                b = Integer.parseInt(st.nextToken());

                list[a].add(b);
                list[b].add(a);
            }

            for (int i = 1; i <= N; i++) {
                if (!visited[i]) {
                    // tree인 경우에만 cnt++
                    if (dfs(0, i)) cnt++;
                }
            }

            // print
            resSb.append(String.format("Case %d: ", step));
            if (cnt == 0) {
                resSb.append("No trees.\n");
            } else if (cnt == 1) {
                resSb.append("There is one tree.\n");
            } else {
                resSb.append(String.format("A forest of %d trees.\n", cnt));
            }
        }
    }

    public static boolean dfs(int before, int x) {
        // tree인지 검사하기 위해 바로 이전 것을 제외하고 이미 visited 한 것을 만나면 바로 false 반환
        for (int i = 0; i < list[x].size(); i++) {
            int next = list[x].get(i);

            if (next == before) continue;
            if (visited[next]) return false;
            visited[next] = true;
            if (!dfs(x, next)) return false;
        }
        return true;
    }
}

[느낀점]

트리의 사이클을 판단하는 문제는 자주 나오는데 많이 풀어봐야겠다.

profile
사용자가 신뢰할 수 있는 튼튼한 서비스 개발을 지향하는 예비 개발자입니다.

0개의 댓글