알고리즘/PS - 백준

[백준 2660 - C++] 회장뽑기 : BFS

excited-hyun 2021. 1. 29. 17:18
반응형

www.acmicpc.net/problem/2660

 

2660번: 회장뽑기

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

www.acmicpc.net

문제

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

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

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

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

 

입력

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

 

출력

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

 

 

풀이

이 문제의 경우도 5567번 결혼식 문제와 마찬가지로 친구 관계를 양방향으로 설정해주어야 한다.

그런뒤 각각의 회원에 대해 bfs탐색을 통해 친구관계를 확인하여 점수를 계산하고 가장 작은 점수의 사람들을 회장 후보로 설정해 주면된다.

이때 친구인지 여부를 체크하는 배열은 매 회원에 대한 bfs탐색을 할때마다 초기화해주어야 한다!

그리고 회장이 될 수 있으려면 몇다리를 걸치든 모든 사람과 친구관계여야한다. 모두와 친구인 사람중 연결다리 수가 적은 사람이 최종 후보가 되는 것이다!

 

#include <cstdio>
#include <iostream>
#include <queue>

using namespace std;

int frd[50][50];
int connect[50];
int score[50];
int can_num;


int main(void){
    int n;
    int f1, f2;
    int F;
    int cnt=1;
    int min_score;
    int frd_cnt;
    queue<pair<int, int>> q;   //번호, 연결 수
    
    scanf("%d", &n);
    min_score = 50;
    
    while(1){
        scanf("%d %d", &f1, &f2);
        if(f1 == -1 && f2 == -1)
            break;
        frd[f1-1][f2-1] = 1;
        frd[f2-1][f1-1] = 1;
        
    }
    
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            connect[j] = 0;
        }
        connect[i] = 1;
        frd_cnt = 1;
        cnt = 1;
        for(int j=0; j<n; j++){
            if(frd[i][j] == 1){
                q.push(make_pair(j, 1));
                connect[j] = 1;
                frd_cnt++;
            }
        }
        
        while(!q.empty()){
            F = q.front().first;
            for(int i=0; i<n; i++){
                if(frd[F][i] == 1 && connect[i] == 0){
                    connect[i] = 1;
                    frd_cnt++;
                    cnt = q.front().second+1;
                    q.push(make_pair(i,cnt));
                }
            }
            q.pop();
            
        }
        if(frd_cnt == n){
            score[i] = cnt;
            if(min_score > cnt)
                min_score = cnt;
        }
    }
    
    for(int i=0; i<n; i++){
        if(score[i] == min_score)
            can_num++;
    }
    printf("%d %d\n", min_score, can_num);
    for(int i=0; i<n; i++){
        if(score[i] == min_score)
            printf("%d ", i+1);
    }
    printf("\n");
}
728x90
반응형