일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 수학
- 에라토스테네스의 체
- 그리디
- lca
- 구현
- 위상정렬
- 펜윅트리
- 세그먼트트리
- 정렬
- LazyPropagation
- 삼분탐색
- DP
- 브루트포스
- BFS
- 플로이드와샬
- 크루스칼
- 비트마스크
- boj
- DisjointSet
- lis
- 좌표압축
- 이분매칭
- 투포인터
- 이분탐색
- 누적합
- 다익스트라
- 이진탐색
- MST
- 백준
- dfs
Archives
- Today
- Total
lastknight00
[백준] 친구비(16562) 본문
문제 링크 : [백준] 친구비(16562)
문제 설명
주어진 모든 사람과 친구가 되려고 하는데 필요한 비용을 구하세요.
단, 친구의 친구는 친구라는 조건을 가지고 최소한의 비용만으로 모든 사람과 친구가 되어야합니다.
입력
N(친구의 수, 1 <= N <= 10,000)
M(친구 관계의 수, 1 <= M <= 10,000)
K(사용할 수 있는 최대 비용, 1 <= 10,000,000)
Vi(i번째 친구와 친구가 되기 위한 비용, 1 <= Vi <= 10,000)
Ai Bi(친구 관계)
5 3 20
10 10 20 20 30
1 3
2 4
5 4
출력
20
카테고리
#DisjointSet
시간 복잡도 상한
O(MlogN) 혹은 O(NlongM)
해결 방법
- 친구의 친구는 친구이기 때문에, 친구 관계를 이용하여 친구로 이어질 수 있는 모든 사람들을 그룹으로 묶습니다.
- 그룹으로 묶인 사람들 중 한명만 친구를 맺으면 그 그룹의 모든 사람과 친구가 될 수 있습니다.
- 즉, 각 그룹별로 최소의 비용만 갖는 사람과 친구를 맺으면 됩니다.
- 그룹을 맺는 방법은 Disjoint set을 사용하면 O(N)에 모든 사람을 그룹으로 묶을 수 있습니다.
- for문을 이용하여 그룹별 최소 비용을 찾고, 그 값들을 출력합니다.
- 단, 총 비용이 K보다 크다면 Oh no를 출력해야 합니다.
시간복잡도
O(N)
코드
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,k,d[10001],e[10001],s[10001],i,a,b;
int f(int a){
return e[a]==a?a:e[a]=f(e[a]);
}
void u(int a,int b){
e[f(a)]=f(b);
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<=n;i++)scanf("%d",d+i),e[i]=i;
while(m--){
scanf("%d%d",&a,&b);
u(a,b);
}
for(i=1;i<=n;i++)s[f(i)]=s[f(i)]?min(s[f(i)],d[i]):d[i];
for(a=0,i=1;i<=n;i++)a+=s[i];
if(k<a)printf("Oh no");
else printf("%d",a);
}
'PS' 카테고리의 다른 글
[백준]Dance Dance Revolution(2342) (0) | 2020.06.26 |
---|---|
[백준] 거짓말(1043) (0) | 2020.06.25 |
[백준] 열쇠(9328) (0) | 2020.06.24 |
[백준] 2048(Easy)(12100) (0) | 2020.06.24 |
[백준] 발전소(1102) (0) | 2020.06.23 |
Comments