https://www.acmicpc.net/problem/2660
문제
월드컵 축구의 응원을 위한 모임에서 회장을 선출하려고 한다. 이 모임은 만들어진지 얼마 되지 않았기 때문에 회원 사이에 서로 모르는 사람도 있지만, 몇 사람을 통하면 모두가 서로 알 수 있다. 각 회원은 다른 회원들과 가까운 정도에 따라 점수를 받게 된다.
예를 들어 어느 회원이 다른 모든 회원과 친구이면, 이 회원의 점수는 1점이다. 어느 회원의 점수가 2점이면, 다른 모든 회원이 친구이거나 친구의 친구임을 말한다. 또한 어느 회원의 점수가 3점이면, 다른 모든 회원이 친구이거나, 친구의 친구이거나, 친구의 친구의 친구임을 말한다.
4점, 5점 등은 같은 방법으로 정해진다. 각 회원의 점수를 정할 때 주의할 점은 어떤 두 회원이 친구사이이면서 동시에 친구의 친구사이이면, 이 두사람은 친구사이라고 본다.
회장은 회원들 중에서 점수가 가장 작은 사람이 된다. 회장의 점수와 회장이 될 수 있는 모든 사람을 찾는 프로그램을 작성하시오.
입력
입력의 첫째 줄에는 회원의 수가 있다. 단, 회원의 수는 50명을 넘지 않는다. 둘째 줄 이후로는 한 줄에 두 개의 회원번호가 있는데, 이것은 두 회원이 서로 친구임을 나타낸다. 회원번호는 1부터 회원의 수만큼 붙어 있다. 마지막 줄에는 -1이 두 개 들어있다.
출력
첫째 줄에는 회장 후보의 점수와 후보의 수를 출력하고, 두 번째 줄에는 회장 후보를 오름차순으로 모두 출력한다.
문제 풀이
bfs 문제.
한 회원의 점수 다른 회원과 만나는 데에 필요한 최대 단계이므로, 각 회원마다 bfs 탐색을 진행하여 몇단계 만에 모든 회원과 친구가 될 수 있는지를 구하면 된다.
큐는 int 타입의 회원 번호, 회원과 몇단계를 거쳐 친구인지를 나타내는 int 타입 변수로 이루어진 pair로 이루어져 있다.
탐색을 시작하기 전, (점수를 구할 회원의 회원 번호, 0) pair를 큐에 push하고, 이미 방문했음을 알리는 isVisited 배열의 점수를 구할 회원의 회원 번호 인덱스를 true로 바꾼다. 이후 큐가 빌 때까지 큐의 front 정보를 가져와 해당 회원의 아직 방문하지 않은 친구들을 모두 큐에 넣고 isVisited 배열 역시 true로 바꾼다. 이때 아직 방문하지 않은 회원들은 친구 -> 친구의 친구와 같이 점수를 구할 회원과의 만남의 단계가 1 늘어난다.
아래는 코드.
#include <iostream>
#include <vector>
#include <queue>
#include <utility>
using namespace std;
queue<pair<int, int>> bfsQueue;
vector<int> candidate;
vector<int>* friends;
bool* isVisited;
int N;
int minPoints = 100;
void bfs(int num)
{
int points = 0;
bfsQueue.push(pair(num, 0));
isVisited[num] = true;
while (!bfsQueue.empty())
{
pair<int, int> current = bfsQueue.front();
int currentNum = current.first;
points = current.second;
for (int i = 0; i < friends[currentNum].size(); i++)
{
if (isVisited[friends[currentNum].at(i)] == false)
{
isVisited[friends[currentNum].at(i)] = true;
bfsQueue.push(pair(friends[currentNum].at(i), points + 1));
}
}
bfsQueue.pop();
}
if (points < minPoints)
{
candidate.clear();
candidate.push_back(num + 1);
minPoints = points;
}
else if (points == minPoints)
{
candidate.push_back(num+1);
}
}
void reset()
{
for (int i = 0; i < N; i++)
{
isVisited[i] = false;
}
}
int main()
{
cin.tie(NULL);
ios::sync_with_stdio(false);
int A, B;
cin >> N;
friends = new vector<int>[N];
isVisited = new bool[N];
reset();
while (true)
{
cin >> A >> B;
if (A == -1 && B == -1)
{
break;
}
else
{
friends[A - 1].push_back(B - 1);
friends[B - 1].push_back(A - 1);
}
}
for (int i = 0; i < N; i++)
{
bfs(i);
reset();
}
cout << minPoints <<" " << candidate.size() << "\n";
for (int i = 0; i < candidate.size(); i++)
{
cout << candidate.at(i) << " ";
}
return 0;
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준 14931] 물수제비 (SUJEBI) (C++) (0) | 2024.05.22 |
---|---|
[백준 1987] 알파벳 (C++) (0) | 2024.05.21 |
[백준 5582] 공통 부분 문자열 (C++) (0) | 2024.05.19 |
[백준 1662] 압축 (C++) (0) | 2024.05.18 |
[백준 24464] 득수 밥 먹이기 (C++) (0) | 2024.05.17 |