※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 2463번 문제인 비용이다.
문제는 아래 링크를 확인하자.
2463번: 비용
첫 번째 줄에 정점의 수 N (1<=N<=100,000)과 간선의 수 M (1<=M<=100,000)이 빈칸을 사이에 두고 주어진다. 다음 M개의 각 줄에 간선 하나에 대한 정보를 나타내는 세 개의 양의 정수 x,y,w가 빈칸을 사이에
www.acmicpc.net
이 문제를 풀기 위해 잠시 생각을 해보자.
어떤 에지가 지워졌을 때 그 두 에지의 양 끝을 잇는 점 사이에 경로가 존재하지 않는다면, 각 에지가 속해있는 component에서 각각 하나씩 뽑은 노드 사이의 경로도 그 순간 전부 사라지게 될 것이다. 따라서, 이러한 에지가 사라질 경우, 이때까지 지운 에지들의 가중치의 합을 답에 두 component의 크기를 곱한 횟수만큼 더하는 것으로 답을 구할 수 있을 것이다.
별개인 집합을 하나로 합치는 Disjoint Set 자료구조를 이용하여 문제에서의 에지가 지워지는 과정을 거꾸로 거슬러올라가면서(에지를 그으며 component를 하나로 합치면서) 위 생각을 이용하면 이 문제를 쉽게 해결할 수 있다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
long long ans = 0;
long long sum = 0;
int arr[100001];
long long cnt[100001];
priority_queue<pair<long long, pair<int, int>>> pq;
int findf(int x) {
if (x == arr[x]) return x;
else return arr[x] = findf(arr[x]);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int N, M; cin >> N >> M;
for (int i = 1;i <= N;i++) {
arr[i] = i;
cnt[i] = 1;
}
for (int i = 0;i < M;i++) {
int x, y; long long w; cin >> x >> y >> w;
pq.push({ w,{x,y} });
sum += w;
}
while (!pq.empty()) {
int x = findf(pq.top().second.first), y = findf(pq.top().second.second);
long long w = pq.top().first;
pq.pop();
if (x != y) {
ans += cnt[x] * cnt[y] * sum;
ans %= 1000000000;
arr[y] = x;
cnt[x] += cnt[y];
}
sum -= w;
}
cout << ans;
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 21236 // C++] Comfortable Cows (0) | 2021.04.30 |
---|---|
[BOJ 21235 // C++] Year of the Cow (0) | 2021.04.29 |
[BOJ 15285 // C++] Connections (0) | 2021.04.27 |
[BOJ 15517 // C++] Array Manipulation at Moloco (Hard) (0) | 2021.04.26 |
[BOJ 1688 // C++] 지민이의 테러 (0) | 2021.04.25 |