백준 2887번 행성 터널
사용한 알고리즘: MST(최소 스패닝 트리)
핵심은 x, y, z축 별로 생각하는 것이였습니다.
각 행성들을 최소 비용으로 연결하여 하나의 컴포넌트를 만드는 것이 목적입니다.
이를 생각하여 x축을 생각해보면,
각 행성들의 x 좌표만을 정렬 해서, A1.x, A2.x, A3.x, ... 와 같이 정렬 됐다고 합시다.
이때 각 행성들은 바로 다음 행성과 연결 될 수 밖에 없습니다. ( 최소 비용을 구하는 것이기 때문)
예를 들어, A1.x 는 A2.x 와 연결 될 수 밖에 없습니다. 즉 A1.x 는 A3.x, A4.x, ... 들과 연결될 수 없습니다.
따라서 이를 생각하여 x, y, z 축 기준으로 각각 정렬하여,
각 이웃한 행성들을 연결하는 비용들을 구해서, 한데 모았습니다.
이후 이 x,y,z축 비용들을 한데 모아놓은 벡터를 정렬하여,
하나의 컴포넌트를 만드는 최소 비용을 구했습니다.
이때 A1, A2 행성이 연결해야하는지 확인하는데에, 같은 컴포넌트인지 union-find를 이용했습니다.
이후 N-1번 만큼 연결이 되면, N개의 행성들은 모두 연결됐으므로 연결하는 과정을 끝내고,
답을 도출했습니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
#define pii pair<int, int> | |
const int INF = 987654321; | |
int uf[100000]; | |
int find(int a){ | |
if(uf[a]<0) return a; | |
return uf[a] = find(uf[a]); | |
} | |
void merge(int a, int b){ | |
a = find(a); | |
b = find(b); | |
if(a==b) return; | |
uf[b]=a; | |
} | |
struct star{ | |
int num; | |
int x; | |
int y; | |
int z; | |
star(): star(0,0,0,0){} | |
star(int _num, int _x, int _y, int _z) : num(_num), x(_x), y(_y), z(_z){} | |
}; | |
vector<star> S; | |
bool cmpX(star &s1, star &s2){ | |
if(s1.x < s2.x) return true; | |
return false; | |
} | |
bool cmpY(star &s1, star &s2){ | |
if(s1.y < s2.y) return true; | |
return false; | |
} | |
bool cmpZ(star &s1, star &s2){ | |
if(s1.z < s2.z) return true; | |
return false; | |
} | |
struct Di{ | |
int A; | |
int B; | |
int length; | |
Di():Di(0,0,0){} | |
Di(int _A, int _B, int _length) : A(_A), B(_B), length(_length){} | |
bool operator<(const Di& rhs) const{ | |
if(length==rhs.length) return A < rhs.A; | |
return length < rhs.length; | |
} | |
}; | |
int N; | |
long long ans; | |
vector<Di> arr; | |
int main(){ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
memset(uf,-1,sizeof(uf)); | |
cin >> N; | |
for (int i = 0; i < N; ++i){ | |
int a, b, c; | |
cin >> a >> b >> c; | |
S.push_back(star(i,a,b,c)); | |
} | |
sort(S.begin(),S.end(),cmpX); | |
for (int i = 0; i < N-1; ++i) | |
arr.push_back(Di(S[i].num,S[i+1].num,S[i+1].x-S[i].x)); | |
sort(S.begin(),S.end(),cmpY); | |
for (int i = 0; i < N-1; ++i) | |
arr.push_back(Di(S[i].num,S[i+1].num,S[i+1].y-S[i].y)); | |
sort(S.begin(),S.end(),cmpZ); | |
for (int i = 0; i < N-1; ++i) | |
arr.push_back(Di(S[i].num,S[i+1].num,S[i+1].z-S[i].z)); | |
sort(arr.begin(),arr.end()); | |
int cnt = 0; | |
for (int i = 0; i < arr.size(); ++i){ | |
int star1 = arr[i].A; | |
int star2 = arr[i].B; | |
if(find(star1)!=find(star2)){ | |
cnt++; | |
merge(star1,star2); | |
ans += arr[i].length; | |
} | |
if(cnt==N-1) break; | |
} | |
cout << ans << '\n'; | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!