https://www.acmicpc.net/problem/2887
2887번: 행성 터널
첫째 줄에 행성의 개수 N이 주어진다. (1 ≤ N ≤ 100,000) 다음 N개 줄에는 각 행성의 x, y, z좌표가 주어진다. 좌표는 -109보다 크거나 같고, 109보다 작거나 같은 정수이다. 한 위치에 행성이 두 개 이
www.acmicpc.net
최소 스패닝 트리 문제이다.
모든 경로의 거리를 배열에 담아두면 100,000 * 100,000이므로 메모리 초과가 난다. 따라서 x,y,z를 따로 두어 비용이 가장 가깝도록 각 좌표마다 정렬을 시킨다.
예를 들어 x의 좌표가 3(A) 2(B) 10(C) 5(D)였다면 x 좌표를 정렬 시킨 후 2(B) 3(A) 5(D) 10(C)가 되고
B -> A로 가는 비용 1
A -> D로 가는 비용 2
D -> C로 가는 비용 5
이런식으로 하는 이유는 각 거리는 min( { abs(x - x1), abs(y - y1), abs(z - z1) } )이기 때문에 가장 작은 값만 가져오면 된다.
이후 각 정보를 저장시켜 크루스칼 알고리즘을 이용해준다.
#include <bits/stdc++.h>
#define l long long
#define INF 2e9
#define p pair<int,int>
#define vc vector<int>
#define F first
#define S second
using namespace std;
int root[100001];
int Find(int x){
if(root[x] == x) return x;
else return root[x] = Find(root[x]);
}
void Union(int x,int y){
x = Find(x), y = Find(y);
if(x < y) root[y] = x;
else root[x] = y;
}
int main(){
ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int n,a,b,c,ans = 0;
cin >> n;
p x[n],y[n],z[n];
vector<tuple<int,int,int>> v;
for(int i=0;i<n;i++) {
cin >> a >> b >> c;
root[i] = i;
x[i] = {a,i};
y[i] = {b,i};
z[i] = {c,i};
}
sort(x,x+n);
sort(y,y+n);
sort(z,z+n);
for(int i=0;i<n-1;i++){
v.emplace_back(x[i+1].F - x[i].F,x[i].S,x[i+1].S);
v.emplace_back(y[i+1].F - y[i].F,y[i].S,y[i+1].S);
v.emplace_back(z[i+1].F - z[i].F,z[i].S,z[i+1].S);
}
sort(v.begin(),v.end());
for(auto &i : v){
tie(a,b,c) = i;
if(Find(b) == Find(c)) continue;
Union(b,c);
ans += a;
}
cout << ans;
}
'baekjoon' 카테고리의 다른 글
7662번 이중 우선순위 큐 (0) | 2022.03.29 |
---|---|
17404번 RGB거리 2 (0) | 2022.03.27 |
4386번 별자리 만들기 (0) | 2022.03.25 |
1647번 도시 분할 계획 (0) | 2022.03.25 |
1753번 최단 경로 (0) | 2022.03.25 |