💡Problem Solving/BOJ

[BOJ 4195] 친구 네트워크 (Java)

gom20 2021. 12. 12. 14:31

문제

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

 

4195번: 친구 네트워크

첫째 줄에 테스트 케이스의 개수가 주어진다. 각 테스트 케이스의 첫째 줄에는 친구 관계의 수 F가 주어지며, 이 값은 100,000을 넘지 않는다. 다음 F개의 줄에는 친구 관계가 생긴 순서대로 주어진

www.acmicpc.net

민혁이는 소셜 네트워크 사이트에서 친구를 만드는 것을 좋아하는 친구이다. 우표를 모으는 취미가 있듯이, 민혁이는 소셜 네트워크 사이트에서 친구를 모으는 것이 취미이다. 어떤 사이트의 친구 관계가 생긴 순서대로 주어졌을 때, 두 사람의 친구 네트워크에 몇 명이 있는지 구하는 프로그램을 작성하시오. 친구 네트워크란 친구 관계만으로 이동할 수 있는 사이를 말한다.

풀이

union-find 기법을 사용하여 풀 수 있다.

 

1. parent 정보와 네트워크 size 정보 담을 자료 구조를 생성한다.

        parent = new HashMap<String, String>(); // 루트 노드 정보
        setSize = new HashMap<String, Integer>(); // 집합의 사이즈

 

2. 입력 전에는 어떤 값이 들어오는지 알 수 없으므로, 입력 받을 때마다 초기값을 할당한다. 

            // 입력 받을 때 초기화
            if(!setSize.containsKey(a)) setSize.put(a, 1);
            if(!setSize.containsKey(b)) setSize.put(b, 1);
            if(!parent.containsKey(a)) parent.put(a, a);
            if(!parent.containsKey(b)) parent.put(b, b);

 

3. 만약 두 친구가 동일한 네트워크에 있지 않을 경우, 동일한 네트워크로 합친다. 

            if(find(a) != find(b)){
                union(a, b);
            }

 

find함수 내 path-compression기법을 통해 각 노드의 parent에 루트 노드 값을 설정하고, 루트 노드 값을 얻어온다. a, b 중 속한 집합의 사이즈가 큰 쪽으로 Union 한다. 각 네트워크의 루트 노드의 집합 사이즈를 갱신 한다.

    private static String find(String a){
        if(parent.get(a) == a) return a;
        parent.put(a, find(parent.get(a)));
        return parent.get(a);
    }
    
    private static void union(String a, String b){
        a = find(a);
        b = find(b);

        if(setSize.get(a) >= setSize.get(b)){
            parent.put(b, a);
            setSize.put(a, setSize.get(a) + setSize.get(b));
            setSize.put(b, 0);
        } else {
            parent.put(a, b);
            setSize.put(b, setSize.get(b) + setSize.get(a));
            setSize.put(a, 0);
        }
    }

 

4. 네트워크의 사이즈를 출력한다. 

// a, b 친구 관계를 맺었으므로 한 명의 루트 노드에 대한 사이즈만 출력하면 됨
bw.write(setSize.get(find(a)) + "\n");

예제

2
3
Fred Barney
Barney Betty
Betty Wilma
3
Fred Barney
Betty Wilma
Barney Betty

 

첫 번째 Test Case

1. Fred Barney 입력

<Parent>

Key Value
Fred Fred
Barney Fred

<setSize>

Key Value
Fred 2
Barney 0

<Tree>

 

2. Barney Betty 입력

<Parent>

Key Value
Fred Fred
Barney Fred
Betty Fred

<setSize>

Key Value
Fred 3
Barney 0
Betty 0

<Tree>

3. Betty Wilma 입력

<Parent>

Key Value
Fred Fred
Barney Fred
Betty Fred
Wilma Fred

<setSize>

Key Value
Fred 4
Barney 0
Betty 0
Wilma 0

<Tree>

Answer:
2
3
4

 

두 번째 Test Case

1. Fred Barney 입력

<Parent>

Key Value
Fred Fred
Barney Fred

<setSize>

Key Value
Fred 2
Barney 0

<Tree>

 

2. Betty Wilma 입력

<Parent>

Key Value
Fred Fred
Barney Fred
Betty Betty
Wilma Betty

<setSize>

Key Value
Fred 2
Barney 0
Betty 2
Wilma 0

<Tree>

3. Barney Betty 입력

<Parent>

Key Value
Fred Fred
Barney Fred
Betty Fred
Wilma Fred

<setSize>

Key Value
Fred 4
Barney 0
Betty 0
Wilma 0

<Tree>

Answer:
2
2
4

소스코드

package unionfind;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.StringTokenizer;

public class BOJ4195 {

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int T = Integer.parseInt(br.readLine());
        for(int i = 0; i < T; i++){
            solution(br, bw);
        }
        bw.flush();
    }

    public static HashMap<String, String> parent;
    public static HashMap<String, Integer> setSize;
    private static void solution(BufferedReader br, BufferedWriter bw) throws Exception {
        int N = Integer.parseInt(br.readLine());
        parent = new HashMap<String, String>(); // 루트 노드 정보
        setSize = new HashMap<String, Integer>(); // 집합의 사이즈

        StringTokenizer st = null;
        for(int i = 0; i < N; i++){
            st = new StringTokenizer(br.readLine());
            String a = st.nextToken();
            String b = st.nextToken();

            // 입력 받을 때 초기화
            if(!setSize.containsKey(a)) setSize.put(a, 1);
            if(!setSize.containsKey(b)) setSize.put(b, 1);
            if(!parent.containsKey(a)) parent.put(a, a);
            if(!parent.containsKey(b)) parent.put(b, b);

            if(find(a) != find(b)){
                union(a, b);
            }
            // a, b 친구 관계를 맺었으므로 한 명의 루트 노드에 대한 사이즈만 출력하면 됨
            bw.write(setSize.get(find(a)) + "\n");
        }
    }

    private static void union(String a, String b){
        a = find(a);
        b = find(b);

        if(setSize.get(a) >= setSize.get(b)){
            parent.put(b, a);
            setSize.put(a, setSize.get(a) + setSize.get(b));
            setSize.put(b, 0);
        } else {
            parent.put(a, b);
            setSize.put(b, setSize.get(b) + setSize.get(a));
            setSize.put(a, 0);
        }
    }

    private static String find(String a){
        if(parent.get(a) == a) return a;
        parent.put(a, find(parent.get(a)));
        return parent.get(a);
    }

}

'💡Problem Solving > BOJ' 카테고리의 다른 글

[BOJ 14501] 퇴사 (Java)  (0) 2021.12.15
[BOJ 2636] 치즈 (Java)  (0) 2021.12.13
[BOJ 14502] 연구소 (Java, Python)  (0) 2021.12.11
[BOJ 2529] 부등호 (Java)  (0) 2021.12.11
[BOJ 15686] 치킨 배달 (Java, Python)  (0) 2021.12.10