문제
https://www.acmicpc.net/problem/16562
16562번: 친구비
첫 줄에 학생 수 N (1 ≤ N ≤ 10,000)과 친구관계 수 M (0 ≤ M ≤ 10,000), 가지고 있는 돈 k (1 ≤ k ≤ 10,000,000)가 주어진다. 두번째 줄에 N개의 각각의 학생이 원하는 친구비 Ai가 주어진다. (1 ≤ Ai ≤ 10,
www.acmicpc.net
문제 요약
N명의 학생이 있을 때, 각 학생들과 친구가 되기 위해 필요한 비용, 친구비가 주어진다.
현재 k원이 있을 때, 모든 학생과 친구가 되기 위한 최소 비용을 출력한다.
+ "친구의 친구는 친구다"를 이용하면, 모든 친구에게 친구비를 지불하지 않아도 된다.
코드
#include <iostream>
#define MAX_N 10000
using namespace std;
// 학생 수, 친구 관계 수, 가지고 있는 돈
int n, m, k;
// i번 학생와 친구가 되기 위한 비용
int cost[MAX_N + 1];
// uf[i] : i번 학생이 속한 그룹 번호
int uf[MAX_N + 1];
// min_cost[i] : i번 그룹 학생들과 친구가 되기 위한 최소 비용
int min_cost[MAX_N + 1];
// x번 학생의 그룹 번호 반환
int find(int x) {
if (uf[x] == x) {
return x;
}
uf[x] = find(uf[x]);
return uf[x];
}
// x번 학생과 y번 학생의 그룹을 같게 하는 함수
void union_(int x, int y) {
x = find(x);
y = find(y);
uf[x] = y;
}
int main() {
// 입력
cin >> n >> m >> k;
// 그룹 번호 초기화
for (int i = 1; i <= n; i++) {
uf[i] = i;
}
for (int i = 1; i <= n; i++) {
cin >> cost[i];
}
for (int i = 0; i < m; i++) {
int a, b;
cin >> a >> b;
if (find(a) == find(b)) continue;
union_(a, b);
}
// 그룹 내 최소 친구비 탐색
for (int i = 1; i <= n; i++) {
int group_num = find(i);
if (min_cost[group_num] == 0) {
min_cost[group_num] = cost[i];
}
else if (min_cost[group_num] > cost[i]) {
min_cost[group_num] = cost[i];
}
}
int res = 0;
// 각 그룹의 최소 친구비의 합이 k원 이하인지 확인
for (int i = 1; i <= n; i++) {
if (min_cost[i] <= k) {
res += min_cost[i];
k -= min_cost[i];
}
else {
cout << "Oh no";
return 0;
}
}
cout << res;
return 0;
}
코드 설명
"친구의 친구는 친구다"라는 성질을 유니온 파인드를 통해 그룹이라는 단위로 표현한다.
각 그룹에서 가장 친구비가 작은 값들을 모두 지불할 수 있는지 확인한다.
'Algorithm Problems > 그래프' 카테고리의 다른 글
[백준/C++] 7576번: 토마토 (1) | 2024.05.17 |
---|---|
[백준/C++] 13565번: 침투 (0) | 2024.05.05 |
[백준/C++] 16953번: A -> B (0) | 2024.03.09 |
[백준/C++] 1240번: 노드사이의 거리 (0) | 2024.03.08 |
[백준/C++] 1068번: 트리 (0) | 2024.02.27 |