Algorithm & Data Structures/BOJ

b4803. ํŠธ๋ฆฌ

Geisha 2025. 4. 28. 17:52

 

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

 

 

 

๐Ÿ“Œ ์ž๋ฐ”(Java)๋กœ ํ‘ธ๋Š” ํŠธ๋ฆฌ - ๋ฐฑ์ค€ 4803 ๐ŸŒณ

์‚ฌ์ดํด ํƒ์ง€ + ์—ฐ๊ฒฐ ์š”์†Œ(ํŠธ๋ฆฌ) ๊ฐœ์ˆ˜ ๊ตฌํ•˜๊ธฐ (Union-Find)

 

 

๐Ÿ”Ž ๋ฌธ์ œ ๊ฐœ์š”

 

๋ฐฑ์ค€ 4803 - ํŠธ๋ฆฌ ๋ฌธ์ œ๋Š”,

 

  • ์ฃผ์–ด์ง„ ๊ทธ๋ž˜ํ”„์—์„œ ์‚ฌ์ดํด์ด ์—†๋Š” ์—ฐ๊ฒฐ ์š”์†Œ(ํŠธ๋ฆฌ)๋ฅผ ์ฐพ์•„์•ผ ํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.
  • ํ•˜๋‚˜์˜ ๊ทธ๋ž˜ํ”„ ์•ˆ์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŠธ๋ฆฌ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ,
  • ์‚ฌ์ดํด์ด ์žˆ๋Š” ์—ฐ๊ฒฐ ์š”์†Œ๋Š” ํŠธ๋ฆฌ๋กœ ์ทจ๊ธ‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 


๐Ÿ’ก ์˜ˆ์ œ ์ž…๋ ฅ

6 3
1 2
2 3
5 6
6 5
2 1
0 0

 

๐Ÿ’ก ์˜ˆ์ œ ์ถœ๋ ฅ

Case 1: A forest of 2 trees.
Case 2: No trees.

 

 


๐Ÿ›  ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ ‘๊ทผ ๋ฐฉ์‹

 

์ด ๋ฌธ์ œ๋Š” ์ „ํ˜•์ ์ธ Union-Find(Disjoint Set) ์•Œ๊ณ ๋ฆฌ์ฆ˜์—

โœ” ์‚ฌ์ดํด ๊ฐ์ง€๋ฅผ ๋ง๋ถ™์ด๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

 


๐Ÿ“Œ ํ•ต์‹ฌ ์ž๋ฃŒ๊ตฌ์กฐ

 

  • p[i] : i๋ฒˆ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • ์‚ฌ์ดํด์ด ๋ฐœ์ƒํ•œ ์ง‘ํ•ฉ์€ ๋ฃจํŠธ๋ฅผ 0์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ํŠธ๋ฆฌ๊ฐ€ ์•„๋‹˜์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ“Œ ์ดˆ๊ธฐํ™”

p = new int[N+1];
for (int i = 0; i <= N; i++)
    p[i] = i;

โœ” ๊ฐ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ๋ฅผ ์ž๊ธฐ ์ž์‹ ์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ“Œ ๊ฐ„์„  ์—ฐ๊ฒฐ (Union ์—ฐ์‚ฐ)

int pa = find(a);
int pb = find(b);
if (pa > pb) {
    int temp = pa;
    pa = pb;
    pb = temp;
}
if (pa == pb) {
    p[pa] = 0; // ์‚ฌ์ดํด ๋ฐœ์ƒ
}
else {
    p[pb] = p[pa]; // ๋ฃจํŠธ ๋ณ‘ํ•ฉ
}

โœ” ๋‘ ๋…ธ๋“œ์˜ ๋ฃจํŠธ๋ฅผ ์ฐพ์•„ ํ•ฉ์นฉ๋‹ˆ๋‹ค.

โœ” ์ด๋ฏธ ๊ฐ™์€ ์ง‘ํ•ฉ์ด๋ผ๋ฉด, ์‚ฌ์ดํด์ด ๋ฐœ์ƒํ•œ ๊ฒƒ์œผ๋กœ ๋ณด๊ณ  ๋ฃจํŠธ๋ฅผ 0์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

 

 

๐Ÿ“Œ ๋ถ€๋ชจ ์ฐพ๊ธฐ (Find ์—ฐ์‚ฐ)

static int find(int a){
    if(p[a] == a) return a;
    return p[a] = find(p[a]);
}

โœ” ๊ฒฝ๋กœ ์••์ถ•(Path Compression)์„ ์ ์šฉํ•˜์—ฌ find ์†๋„๋ฅผ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค.

 

 

๐Ÿ“Œ ์ตœ์ข… ํŠธ๋ฆฌ ๊ฐœ์ˆ˜ ์„ธ๊ธฐ

HashSet<Integer> set = new HashSet<>();
for (int i = 1; i <= N; i++) {
    int tree = find(i);
    if (tree > 0)
        set.add(tree);
}

โœ” ๋ฃจํŠธ๊ฐ€ 0์ด ์•„๋‹Œ ๋…ธ๋“œ๋“ค์„ ์ง‘ํ•ฉ์— ์ถ”๊ฐ€ํ•ด

โœ” ํŠธ๋ฆฌ์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ผ๋‹ค.

 

 

๐Ÿ“Œ ์ถœ๋ ฅ ํฌ๋งท

if (set.size() == 1)
    sb.append("There is one tree.\n");
else if (set.isEmpty())
    sb.append("No trees.\n");
else
    sb.append("A forest of " + set.size() + " trees.\n");

โœ” ํŠธ๋ฆฌ ๊ฐœ์ˆ˜์— ๋”ฐ๋ผ ๋งž๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

 


โœ… ์ •๋ฆฌ

ํ•ต์‹ฌ ํฌ์ธํŠธ ์„ค๋ช…
์‚ฌ์ดํด์ด ์ƒ๊ธฐ๋ฉด ๋ฃจํŠธ๋ฅผ 0์œผ๋กœ ์„ธํŒ… ์‚ฌ์ดํด ๋ฐœ์ƒ ์‹œ ํ•ด๋‹น ์—ฐ๊ฒฐ ์š”์†Œ๋ฅผ ํŠธ๋ฆฌ๋กœ ์ทจ๊ธ‰ํ•˜์ง€ ์•Š๊ธฐ
find()์—์„œ ๊ฒฝ๋กœ ์••์ถ• ์‹œ๊ฐ„ ๋ณต์žก๋„ ์ตœ์ ํ™” (๊ฑฐ์˜ O(1))
set์œผ๋กœ ๊ณ ์œ ํ•œ ๋ฃจํŠธ๋งŒ ์นด์šดํŠธ ํŠธ๋ฆฌ์˜ ๊ฐœ์ˆ˜๋ฅผ ์ •ํ™•ํžˆ ๊ตฌํ•˜๊ธฐ ์œ„ํ•จ

 

 


 

๐Ÿ”ฅ ์ฝ”๋“œ ์ „์ฒด (์ •๋ฆฌ)

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

public class b4803 {
    static int N, M;
    static int[] p;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        int cnt = 1;
        
        while (true) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            N = Integer.parseInt(st.nextToken());
            M = Integer.parseInt(st.nextToken());
            if (N == 0 && M == 0) break;

            p = new int[N+1];
            for (int i = 0; i <= N; i++)
                p[i] = i;

            for (int i = 0; i < M; i++) {
                st = new StringTokenizer(br.readLine());
                int a = Integer.parseInt(st.nextToken());
                int b = Integer.parseInt(st.nextToken());
                union(a, b);
            }

            sb.append("Case ").append(cnt++).append(": ");
            HashSet<Integer> set = new HashSet<>();
            for (int i = 1; i <= N; i++) {
                int tree = find(i);
                if (tree > 0)
                    set.add(tree);
            }

            if (set.size() == 1)
                sb.append("There is one tree.\n");
            else if (set.isEmpty())
                sb.append("No trees.\n");
            else
                sb.append("A forest of ").append(set.size()).append(" trees.\n");
        }
        System.out.println(sb);
    }

    static int find(int a) {
        if (p[a] == a) return a;
        return p[a] = find(p[a]);
    }

    static void union(int a, int b) {
        int pa = find(a);
        int pb = find(b);
        if (pa > pb) {
            int temp = pa;
            pa = pb;
            pb = temp;
        }
        if (pa == pb) {
            p[pa] = 0;
        } else {
            p[pb] = p[pa];
        }
    }
}