https://www.acmicpc.net/problem/17398
목적
통신망을 주어진 순으로 나누는데 필요한 비용을 구하자.
접근법
1. 통신망을 구축해 나가는데에는 disjoint-set을 이용하면 될 것이란 생각은 든다. 하지만 해당 알고리즘으로 합친 집합을 분리하는 것은 불가능(?방법이 있을 수도 있습니다...)하다. 하지만, 분리하는 과정을 거꾸로 한다면 union-find 만으로 해결이 가능하다.
2. 제거해야 할 열결 번호를 저장하고, 일단은 제거할 번호 리스트에 없는 연결만 수행하자. 그리고 제거할 번호 리스트의 역순으로 연결을 수행하며 비용을 연산하면 된다.
3. 하마터면, link/cut tree 자료구조를 공부할 뻔.... 아직은 미뤄두고 싶은...
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
#include<bits/stdc++.h>
#define f(i,l,r) for(int i=l;i<=r;++i)
#define fr(i,l,r) for(int i=l;i>=r;--i)
using namespace std;
typedef long long ll;
const int LEN = 1e5+1;
int p[LEN],e[LEN][2],r[LEN];
bool chk[LEN]{};
int find(int x) {
return p[x] < 0 ? x : p[x] = find(p[x]);
}
void merge(int x, int y) {
if (p[x] > p[y]) swap(x, y);
p[x] += p[y];
p[y] = x;
}
int main() {
ios_base::sync_with_stdio(0);
memset(p, -1, sizeof(p));
int n, m, q,tmp;
cin >> n >> m >> q;
f(i, 1, m)cin >> e[i][0] >> e[i][1];
fr(i, q, 1) cin >> r[i], chk[r[i]] = true;
f(i, 1, m) if(!chk[i]){
int x = find(e[i][0]), y = find(e[i][1]);
if (x != y)merge(x, y);
}
ll ans = 0;
f(i, 1, q){
int x = find(e[r[i]][0]), y = find(e[r[i]][1]);
if (x == y)continue;
ans += (p[x] * p[y]);
merge(x, y);
}
cout << ans;
return 0;
}
|
문제 설명과 코드에 대한 피드백은 언제나 환영합니다.
다양한 의견 댓글로 남겨주세요.
'Problem Solving > BOJ 백준' 카테고리의 다른 글
[ BOJ 백준 12015번 - 가장 긴 증가하는 부분 수열 2 ] 해설 및 코드 (0) | 2020.01.18 |
---|---|
[ BOJ 백준 3780번 - 네트워크 연결 ] 해설 및 코드 (0) | 2020.01.05 |
[ BOJ 백준 10775번 - 공항 ] 해설 및 코드 (0) | 2020.01.04 |
[ BOJ 백준 11085번 - 군사 이동 ] 해설 및 코드 (0) | 2020.01.04 |
[ BOJ 백준 3197번 - 백조의 호수 ] 해설 및 코드 (0) | 2020.01.04 |