PS/백준

[BOJ] 백준 2660번 : 회장뽑기 (JAVA)

제이온 (Jayon) 2020. 8. 1.

문제

월드컵 축구의 응원을 위한 모임에서 회장을 선출하려고 한다. 이 모임은 만들어진지 얼마 되지 않았기 때문에 회원 사이에 서로 모르는 사람도 있지만, 몇 사람을 통하면 모두가 서로 알 수 있다. 각 회원은 다른 회원들과 가까운 정도에 따라 점수를 받게 된다.

 

예를 들어 어느 회원이 다른 모든 회원과 친구이면, 이 회원의 점수는 1점이다. 어느 회원의 점수가 2점이면, 다른 모든 회원이 친구이거나 친구의 친구임을 말한다. 또한 어느 회원의 점수가 3점이면, 다른 모든 회원이 친구이거나, 친구의 친구이거나, 친구의 친구의 친구임을 말한다.

 

4점, 5점 등은 같은 방법으로 정해진다. 각 회원의 점수를 정할 때 주의할 점은 어떤 두 회원이 친구사이이면서 동시에 친구의 친구사이이면, 이 두사람은 친구사이라고 본다.

 

회장은 회원들 중에서 점수가 가장 작은 사람이 된다. 회장의 점수와 회장이 될 수 있는 모든 사람을 찾는 프로그램을 작성하시오.

 

 

입력

입력의 첫째 줄에는 회원의 수가 있다. 단, 회원의 수는 50명을 넘지 않는다. 둘째 줄 이후로는 한 줄에 두 개의 회원번호가 있는데, 이것은 두 회원이 서로 친구임을 나타낸다. 회원번호는 1부터 회원의 수만큼 붙어 있다. 마지막 줄에는 -1이 두 개 들어있다.

 

 

출력

첫째 줄에는 회장 후보의 점수와 후보의 수를 출력하고, 두 번째 줄에는 회장 후보를 오름차순으로 모두 출력한다.

 

 

풀이

플로이드 와샬 알고리즘을 활용하는 문제였습니다.

주어진 일부분의 친구 관계를 가지고 모든 사람들의 친구 관계로 확장시켜야하므로, 모든 정점에 대하여 모든 정점의 최단거리를 구하는 플로이드 와샬 알고리즘을 사용해야합니다.

 

풀이를 설명하기에 앞서, 주어진 문제의 예시에 해당하는 친구 관계를 그래프로 표현해 보겠습니다.

 

 

 

 

친구 관계는 양방향 그래프이므로 위와 같은 형태가 될 것입니다.

그러면, 이제 "1과 2는 친구이고, 2와 3은 친구이므로 1과 3은 친구이다." 라는 문장을 생각하면서 친구 점수를 구해봅시다.

 

문제에서 어떤 사람이 다른 모든 사람과 친구이면 1점이고, 다른 모든 사람이 친구이거나 친구의 친구면 2점이라고 하였습니다.

 

이것을 조금 그래프적인 시각으로 보자면, A라는 정점에서 B라는 정점으로 1번만으로 이동할 수 있으면 1점이고, 2번 이동해야하면 2점입니다.

 

따라서 모든 정점에서 모든 정점 사이의 최단거리를 구하고, 특정 정점에서 다른 정점으로의 최단거리가 가장 큰 값이 친구 점수가 됩니다.

 

위 내용을 표로 표현해 보면 아래와 같습니다.

 

 

  1 2 3 4 5
1 0 1 2 2 3
2 1 0 1 1 2
3 2 1 0 1 1
4 2 1 1 0 1
5 3 2 1 1 0

 

 

그리고 친구 점수를 정리하면 아래와 같습니다. 각 사람마다 가장 높은 점수를 뽑아내면 됩니다.

 

 

1 2 3 4 5
3 2 2 2 3

 

 

따라서 회장의 점수는 2점이고, 회장이 될 수 있는 후보는 3명이며, 후보의 명단은 2, 3, 4가 되겠습니다.

 

 

아래는 위 과정을 정리한 소스코드입니다.

 

 

소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
 
public class Main {
    static final int INF = 987654321;
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st;
 
        int N = Integer.parseInt(br.readLine());
 
        int[][] arr = new int[N + 1][N + 1];
 
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                if (i != j) {
                    arr[i][j] = INF;
                }
            }
        }
 
        while (true) {
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken());
            int y = Integer.parseInt(st.nextToken());
 
            if (x == -1 && y == -1) {
                break;
            }
 
            arr[x][y] = arr[y][x] = 1// 친구 관계는 양방향
        }
 
        // 플로이드 와샬 알고리즘 수행
        for (int k = 1; k <= N; k++) {
            for (int i = 1; i <= N; i++) {
                for (int j = 1; j <= N; j++) {
                    if (arr[i][j] > arr[i][k] + arr[k][j]) {
                        arr[i][j] = arr[i][k] + arr[k][j];
                    }
                }
            }
        }
 
        int readerScore = INF;
 
        int[] scoreArr = new int[N + 1]; // 친구 점수 목록
 
        for (int i = 1; i <= N; i++) {
            int score = 0;
            for (int j = 1; j <= N; j++) {
                if (arr[i][j] != INF) {
                    score = Math.max(score, arr[i][j]);
                }
            }
 
            scoreArr[i] = score;
            readerScore = Math.min(readerScore, score);
        }
 
        StringBuilder title = new StringBuilder();
        title.append(readerScore + " ");
 
        int readerNum = 0;
 
        StringBuilder body = new StringBuilder();
        for (int i = 1; i <= N; i++) {
            if (readerScore == scoreArr[i]) {
                readerNum++;
                body.append(i + " ");
            }
        }
 
        title.append(readerNum + "\n");
 
        bw.write(title.toString());
        bw.write(body.toString() + "\n");
        bw.flush();
        bw.close();
        br.close();
    }
 
}
cs

 

지적 혹은 조언 환영합니다! 언제든지 댓글로 남겨주세요.

댓글

추천 글