반응형
2660번: 회장뽑기
입력의 첫째 줄에는 회원의 수가 있다. 단, 회원의 수는 50명을 넘지 않는다. 둘째 줄 이후로는 한 줄에 두 개의 회원번호가 있는데, 이것은 두 회원이 서로 친구임을 나타낸다. 회원번호는 1부터
www.acmicpc.net
1. 문제 설명
예제 1에서 1번부터 5번 회원의 점수는 각각 3점, 2점, 2점, 2점, 3점이다.
그러므로 가장 작은 점수는 2점이 되고, 점수가 2점인 2, 3, 4번 회원 총 3명이 회장 후보가 되는 것이다.
2. 구현 아이디어 1 - 틀렸습니다.
1. 현재 노드에서 가장 거리가 먼 노드까지의 거리가 해당 회원의 점수가 된다.
2. 모든 회원의 점수를 배열에 저장하고, 배열의 최솟값(=score)을 찾는다.
3. 값이 score인 원소의 index를 candidate라는 배열에 저장한다.
4. 첫째 줄에는 score와 candidate 배열의 길이를 출력한다.
5. 둘째 줄에는 candidate 배열의 원소를 순서대로 출력한다.
1번을 구현하기 위해 DFS를 사용했다.
#include <bits/stdc++.h>
using namespace std;
int n; // 회원의 수
map<int, vector<int>> mp; // 인접 그래프
int a, b;
void dfs(map<int, vector<int>> &mp, vector<int> &arr, int start) {
// 초기화
stack<pair<int, int>> s;
vector<bool> visited(n+1);
// 시작 노드 삽입
s.push({start, 0});
visited[start] = true;
while (!s.empty()) {
int cur = s.top().first;
int cScore = s.top().second;
if (cScore > arr[start]) arr[start] = cScore;
s.pop();
for (auto node : mp[cur]) {
if (visited[node]) continue;
s.push({node, cScore + 1});
visited[node] = true;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n;
while (true) {
cin >> a >> b;
if (a == -1 && b == -1) break;
mp[a].push_back(b);
mp[b].push_back(a);
}
vector<int> arr = vector<int>(n+1);
arr[0] = INT_MAX;
for (int i = 1; i < n+1; ++i) {
dfs(mp, arr, i);
}
int score = *min_element(arr.begin(), arr.end());
int ret = 0;
vector<int> candidate;
for (int i = 1; i < n+1; ++i) {
if (arr[i] == score) {
ret ++;
candidate.push_back(i);
}
}
cout << score << " " << ret << "\n";
for (auto elem : candidate) {
cout << elem << " ";
}
return 0;
}
반례
5
1 2
2 3
3 4
4 5
5 1
-1 -1
위와 같은 입력이 들어올 경우 3번과 4번 노드의 점수는 2점이지만, if(cScore > arr[start]) arr[start] = cScore; 이라는 부분 때문에 무조건 더 큰 3이 저장된다.
3. 구현 아이디어 2 - 맞았습니다 !!
DFS 코드를 보완해서 문제를 풀 수도 있지만 해당 문제를 플로이드-와샬 알고리즘으로도 풀 수 있다는걸 알고 플로이드-와샬 알고리즘을 사용하여 문제를 다시 풀었다.
n의 최댓값이 50으로 크지 않기 때문에 3중 반복문을 사용하여도 제한 조건 내에서 문제를 풀 수 있다.
#include <bits/stdc++.h>
using namespace std;
#define INF 987654321
int n; // 회원의 수
vector<vector<int>> arr = vector(51, vector<int>(51, INF));
int a, b;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n;
while (true) {
cin >> a >> b;
if (a == -1 && b == -1) break;
arr[a][b] = 1;
arr[b][a] = 1;
}
for (int k = 1; k < n+1; ++k) {
for (int i = 1; i < n+1; ++i) {
for (int j = 0; j < n+1; ++j) {
if (i == j) arr[i][j] = 0;
arr[i][j] = min(arr[i][j], arr[i][k] + arr[k][j]);
}
}
}
vector<int> candidate = vector<int>(n+1);
for (int i = 1; i < n+1; ++i) {
for (int j = 1; j < n+1; ++j) {
if (arr[i][j] > candidate[i]) candidate[i] = arr[i][j];
}
}
int score = INF;
vector<int> ret;
// 회장 후보의 점수 계산
for (int i = 1; i < n+1; ++i) {
if (candidate[i] < score) score = candidate[i];
}
// 회장 후보 계산
for (int i = 1; i < n+1; ++i) {
if (candidate[i] == score) {
ret.push_back(i);
}
}
cout << score << " " << ret.size() << "\n";
for (auto elem : ret) {
cout << elem << " ";
}
return 0;
}
반응형