Algorithm

백준 2660번 <회장 뽑기>

seungh2 2022. 9. 24. 23:57

백준 알고리즘 2660번

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

 

2660번: 회장뽑기

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

www.acmicpc.net


2660번

N명의 회원이 있는 모임에서 회장을 선출하려고 한다. 회장을 선출할 때 사용할 점수를 내서 점수가 가장 낮은 사람이 회장이 될 수 있다. 회장 후보의 점수와 후보의 수, 후보들을 구하여라.

점수는 아래와 같이 낸다.

  • 어느 회원이 다른 모든 회원과 친구이면 1점.
  • 어느 회원이 모든 회원과의 관계가 친구이거나, 친구의 친구 관계이면 2점.
  • 어느 회원이 모든 회원과의 관계가 친구이거나, 친구의 친구이거나, 친구의 친구의 친구 관계이면 3점.

 

입력으로 첫 줄에 회원의 수 N이 들어오고 그 다음 줄부터 친구관계가 들어온다.

 

출력으로 첫 줄에 회장 후보의 점수와 후보의 수를 출력하고 그 다음 줄에 후보들을 출력하면 된다. 


문제 해결

BFS를 이용하여 문제를 풀었다.

회원의 수 N 이 50밖에 되지 않기 때문에 각 회원마다 BFS를 돌려서 점수가 몇 점인지 구했다.

 

check 함수로 점수를 구한다.

  • check 함수는 모든 회원과의 관계를 확인했는지를 의미하는 boolean 배열 chk와 점수를 구하는 회원의 번호 num을 파라미터로 갖는다.
  • num과 친구인 회원을 큐에 넣어 시작점으로 활용한다. 큐에 넣을 때 방문을 체크하기 위해 chk 배열의 값을 true로 바꾼다.
  • 큐가 빌 때까지 while 문을 돌린다.
  • 이때 큐의 크기만큼 for문을 돌려서 같은 관계인 회원들을 볼 수 있다. 
  • 즉, 처음 for문으로 큐에서 나오는 회원들은 num과 친구 관계이고, 두 번째 for문에서 큐에서 나오는 회원들은 num과 친구의 친구 관계이고, 세 번째 for문에서 큐에서 나오는 회원들은 num과 친구의 친구의 친구 관계이다.
  • 또한 점수가 가장 낮은 후보를 찾기 때문에 현재 점수(score)가 회장 후보의 점수(minScore)보다 크다면 더 이상 볼 필요가 없기 때문에 함수를 빠져나간다.
  • while문을 빠져나와서 모든 회원과 관계를 맺었는지 확인하고 그렇지 않다면 함수를 빠져나간다.
  • 점수가 가장 낮은 후보를 찾기 때문에 minScore와 answer를 update한다.

코드

package boj2660;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Queue;

/*
 * 회원의 최대 수가 50으로 작기 때문에 모든 회원의 점수를 구하여 가장 낮은 점수를 구했다.
 * 점수를 구하는 방법은 BFS를 사용하였다.
 * num과 친구인 회원을 큐에 넣어서 시작점으로 활용한다.
 * 큐의 크기만큼 for문을 돌려서 같은 관계인 회원들을 본다.
 * 이때 점수(score)가 회장 후보의 점수(minScore)보다 크다면 더 이상 볼 필요가 없기 때문에 return -> 가지치기
 * while문이 끝나면 모든 회원과의 관계를 갖는지 확인한다.
 * minScore와 answer를 update한다.
 * */

public class Main {
	static int N, minScore;
	static ArrayList<Integer> answer;
	static ArrayList<Integer>[] friends;

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());
		friends = new ArrayList[N + 1];
		for (int i = 0; i < N + 1; i++) {
			friends[i] = new ArrayList<>();
		}

		String[] inArr = br.readLine().split(" ");
		int a = Integer.parseInt(inArr[0]);
		int b = Integer.parseInt(inArr[1]);
		while (a != -1 && b != -1) {
			friends[a].add(b);
			friends[b].add(a);

			inArr = br.readLine().split(" ");
			a = Integer.parseInt(inArr[0]);
			b = Integer.parseInt(inArr[1]);
		}

		minScore = Integer.MAX_VALUE;
		answer = new ArrayList<>();
		for (int i = 1; i < N + 1; i++) {
			check(new boolean[N + 1], i);
		}
		Collections.sort(answer);
		System.out.println(minScore + " " + answer.size());
		for (int i = 0; i < answer.size(); i++) {
			System.out.print(answer.get(i) + " ");
		}

	}

	public static void check(boolean[] chk, int num) {
		int score = 0;
		chk[num] = true;
		Queue<Integer> queue = new ArrayDeque<>();
		for (int i = 0; i < friends[num].size(); i++) {
			chk[friends[num].get(i)] = true;
			queue.add(friends[num].get(i));
		}

		while (!queue.isEmpty()) {
			int size = queue.size();
			score++;
			if (score > minScore) {
				return;
			}
			for (int i = 0; i < size; i++) {
				int a = queue.poll();
				for (int j = 0; j < friends[a].size(); j++) {
					if (!chk[friends[a].get(j)]) {
						chk[friends[a].get(j)] = true;
						queue.add(friends[a].get(j));
					}
				}
			}
		}

		for (int i = 1; i < N+1; i++) {
			if (!chk[i]) {
				return;
			}
		}

		if (minScore > score) {
			answer = new ArrayList<>();
			answer.add(num);
			minScore = score;
		} else if (minScore == score) {
			answer.add(num);
		}
	}

}

결과


 

728x90