문제 링크
https://www.acmicpc.net/problem/10021
문제
Due to a lack of rain, Farmer John wants to build an irrigation system to send water between his N fields (1 <= N <= 2000).
Each field i is described by a distinct point (xi, yi) in the 2D plane, with 0 <= xi, yi <= 1000. The cost of building a water pipe between two fields i and j is equal to the squared Euclidean distance between them:
(xi - xj)^2 + (yi - yj)^2
FJ would like to build a minimum-cost system of pipes so that all of his fields are linked together -- so that water in any field can follow a sequence of pipes to reach any other field.
Unfortunately, the contractor who is helping FJ install his irrigation system refuses to install any pipe unless its cost (squared Euclidean length) is at least C (1 <= C <= 1,000,000).
Please help FJ compute the minimum amount he will need pay to connect all his fields with a network of pipes.
입력
- Line 1: The integers N and C.
- Lines 2..1+N: Line i+1 contains the integers xi and yi.
출력
- Line 1: The minimum cost of a network of pipes connecting the fields, or -1 if no such network can be built.
예제 입력 1
3 11
0 2
5 0
4 3
예제 출력 1
46
힌트
Input Details
There are 3 fields, at locations (0,2), (5,0), and (4,3). The contractor will only install pipes of cost at least 11.
Output Details
FJ cannot build a pipe between the fields at (4,3) and (5,0), since its cost would be only 10. He therefore builds a pipe between (0,2) and (5,0) at cost 29, and a pipe between (0,2) and (4,3) at cost 17.
알고리즘 분류
- 최소 스패닝 트리
풀이
모든 필드를 잇는데, 이 때 간선의 가중치는 유클리드 거리이다.
N(N - 1)개의 간선을 만들고 가중치를 기준으로 오름차순 정렬한다.
최소 스패닝 트리를 만드는데, 이 때 가중치 C 미만인 간선은 버린다.
모든 필드가 이어졌다면 가중치의 합산을 출력하고, 그렇지 않으면 -1을 출력한다.
코드
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#define MAX 2001
#define INF 4e9
#define LL long long
#define FASTIO cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
using namespace std;
struct EDGE {
int From, To;
LL Cost;
};
int N;
LL C;
vector<pair<int, int> > Fields;
int Parent[MAX];
vector<EDGE> Edges;
LL Answer = INF;
void init() {
for (int i = 0; i < MAX; i++) {
Parent[i] = i;
}
}
void input() {
cin >> N >> C;
Fields.resize(N);
for (int i = 0; i < N; i++) {
cin >> Fields[i].first >> Fields[i].second;
}
}
int find_Parent(int X) {
if (Parent[X] == X) {
return X;
}
return Parent[X] = find_Parent(Parent[X]);
}
void union_Group(int X, int Y) {
int PX = find_Parent(X);
int PY = find_Parent(Y);
if (PX < PY) {
Parent[PY] = PX;
}
else {
Parent[PX] = PY;
}
}
bool comp(EDGE A, EDGE B) {
return (A.Cost < B.Cost);
}
void settings() {
for (int i = 0; i < N; i++) {
int X1 = Fields[i].first;
int Y1 = Fields[i].second;
for (int j = (i + 1); j < N; j++) {
int X2 = Fields[j].first;
int Y2 = Fields[j].second;
LL Cost = (X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2);
Edges.push_back({ i + 1,j + 1,Cost });
}
}
sort(Edges.begin(), Edges.end(), comp);
LL Sum = 0;
for (int i = 0; i < (int)Edges.size(); i++) {
int From = Edges[i].From;
int To = Edges[i].To;
LL Cost = Edges[i].Cost;
if (Cost < C) continue;
if (find_Parent(From) != find_Parent(To)) {
union_Group(From, To);
Sum += Cost;
}
}
for (int i = 1; i <= N; i++) {
if (find_Parent(i) != 1) {
return;
}
}
Answer = min(Answer, Sum);
}
void find_Answer() {
if (Answer == INF) {
cout << "-1\n";
}
else {
cout << Answer << "\n";
}
}
int main() {
FASTIO
init();
input();
settings();
find_Answer();
return 0;
}
'BOJ > Gold' 카테고리의 다른 글
[BOJ/Gold 5] 백준 17070 파이프 옮기기 1(Java) (2) | 2024.09.10 |
---|---|
[BOJ/Gold 5] 백준 2421 저금통(C++) (2) | 2024.09.08 |
[BOJ/Gold 5] 백준 25682 체스판 다시 칠하기 2(C++) (0) | 2024.07.11 |
[BOJ/Gold 5] 백준 31849 편세권(C++, Java) (1) | 2024.07.01 |
[BOJ/Gold 4] 백준 31804 Chance!(C++) (0) | 2024.05.18 |