일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- boj 2636
- 백준 1697
- 백준 2661
- boj 10800
- 2167
- boj 1697
- 백준 19238
- 백준 10800
- boj 19238
- boj 2108
- boj 2470
- 백준 2167
- 백준 2636
- boj 2667
- boj 1806
- 2636
- boj 2206
- 백준 2206
- 10800
- boj 2167
- 백준 2470
- 백준 1503
- boj 2635
- boj 2178
- 백준 2178
- 백준 2635
- boj 1503
- 백준 1806
- boj 2661
- 백준 2108
- Today
- Total
말랑말랑한 개발자 이야기
[백준 16562번] 친구비 본문
[백준 16562번] 친구비
문제
19학번 이준석은 학생이 N명인 학교에 입학을 했다. 준석이는 입학을 맞아 모든 학생과 친구가 되고 싶어한다. 하지만 준석이는 평생 컴퓨터랑만 대화를 하며 살아왔기 때문에 사람과 말을 하는 법을 모른다. 그런 준석이에게도 희망이 있다. 바로 친구비다!
학생 i에게 Ai만큼의 돈을 주면 그 학생은 1달간 친구가 되어준다! 준석이에게는 총 k원의 돈이 있고 그 돈을 이용해서 친구를 사귀기로 했다. 막상 친구를 사귀다 보면 돈이 부족해질 것 같다는 생각을 하게 되었다. 그래서 준석이는 “친구의 친구는 친구다”를 이용하기로 했다.
준석이는 이제 모든 친구에게 돈을 주지 않아도 된다!
위와 같은 논리를 사용했을 때, 가장 적은 비용으로 모든 사람과 친구가 되는 방법을 구하라.
입력
첫 줄에 학생 수 N (1 ≤ N ≤ 10,000)과 친구관계 수 M (0 ≤ M ≤ 10,000), 가지고 있는 돈 k (1 ≤ k ≤ 10,000,000)가 주어진다.
두번째 줄에 N개의 각각의 학생이 원하는 친구비 Ai가 주어진다. (1 ≤ Ai ≤ 10,000, 1 ≤ i ≤ N)
다음 M개의 줄에는 숫자 v, w가 주어진다. 이것은 학생 v와 학생 w가 서로 친구라는 뜻이다.
출력
준석이가 모든 학생을 친구로 만들 수 있다면, 친구로 만드는데 드는 최소비용을 출력한다. 만약 친구를 다 사귈 수 없다면, “Oh no”(따옴표 제거)를 출력한다.
풀이
#include <iostream>
using namespace std;
int arr[10001];
int u_find(int a){
if(arr[a] == a) return a;
else return arr[a] = u_find(arr[a]);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int N, M, k; cin >> N >> M >> k;
int w[10001];
for(int i=1;i<=N;i++) arr[i] = i;
for(int i=1;i<=N;i++) cin >> w[i];
for(int i=0;i<M;i++){
int a, b; cin >> a >> b;
a = u_find(a);
b = u_find(b);
if(w[a] < w[b]) arr[b] = a;
else arr[a] = b;
}
int sum = 0;
for(int i=1;i<=N;i++){
if(arr[i] == i) sum += w[i];
}
if(sum <= k) cout << sum;
else cout << "Oh no";
return 0;
}
유니온 파인드 문제는 u_find 함수의 작성을 고정으로 외워두면 편하다. u_find함수로 소속된 집합(?)의 번호를 구할 수 있꼬 합치는 과정을 거치게 되는데 지금까지 풀었던 유니온 파인드 문제들에서는 대부분이 그 번호가 작은 쪽으로 합쳐서 처음에는 그렇게 풀었다. 작은 쪽으로 합치고, 마지막에 각 번호에서 친구비가 가장 작은 것을 고르도록 했더니 이중포문을 돌기때문에 위 코드보다 시간이 좀 더 걸렸다.
작은 번호로 합치는 게 아닌 친구비가 작은 쪽으로 합치도록 하면 위 과정을 생략할 수 있었다.
'알고리즘 > 백준' 카테고리의 다른 글
[백준 15732번] 도토리 숨기기 (0) | 2021.06.21 |
---|---|
[백준 10775번] 공항 (0) | 2021.06.18 |
[백준 20152번] Game Addiction (0) | 2021.06.18 |
[백준 17951번] 흩날리는 시험지 속에서 내 평점이 느껴진거야 (0) | 2021.06.18 |
[백준 16139번] 인간-컴퓨터 상호작용 (0) | 2021.06.18 |