https://www.acmicpc.net/problem/2887
2887번: 행성 터널
첫째 줄에 행성의 개수 N이 주어진다. (1 ≤ N ≤ 100,000) 다음 N개 줄에는 각 행성의 x, y, z좌표가 주어진다. 좌표는 -109보다 크거나 같고, 109보다 작거나 같은 정수이다. 한 위치에 행성이 두 개 이
www.acmicpc.net
솔루션
처음에 https://www.acmicpc.net/problem/4386와 비슷해서 그대로 풀려고 했는데, 범위가 10만이라 무지성으로 했다간 시간초과를 받을 것 같았다.
그래서 조금 더 생각을 해 보니, 각각의 좌표를 정렬하여, 각각의 차를 모두 우선순위 큐에 넣어 준 뒤, MST 알고리즘을 수행하는 것이 좋아 보인다고 생각을 했고 성공을 했다.
먼저 각각의 좌표를 따로 따로 입력을 받는다. (인덱스 정보도 같이 둔다.)
각각을 좌표를 정렬 해 주고
우선순위 큐에 앞의 값과 차이를 배열에 담는다.
가장 차이가 작은 값 부터 유니온 파인드를 통해 연결 되었는지 안되었는지, 판별하고 연결한다.
코드
#define ll long long int
#define INF 987654321123
#define pint pair<int,int>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int parent[100002];
int getParent(int x) {
if (x == parent[x]) return x;
else return parent[x] = getParent(parent[x]);
}
void setUnion(int a, int b) {
a = getParent(a);
b = getParent(b);
if (a > b) parent[a] = b;
else parent[b] = a;
}
bool isUnion(int a, int b) {
a = getParent(a);
b = getParent(b);
return a == b;
}
pint axisX[100002];
pint axisY[100002];
pint axisZ[100002];
int N;
struct pa {
int idx1, idx2;
ll cost;
bool operator<(const struct pa& t)const {
if (cost == t.cost) {
return idx1 > t.idx1;
}
return cost > t.cost;
}
};
ll ans;
int cnt;
priority_queue<struct pa> pq;
void kruskal(void) {
while (!pq.empty()) {
int idx1 = pq.top().idx1;
int idx2 = pq.top().idx2;
ll cost = pq.top().cost;
pq.pop();
if (isUnion(idx1, idx2)) continue;
setUnion(idx1, idx2);
ans += cost;
}
return;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> N;
for (int i = 0; i < N; i++) {
cin >> axisX[i].first;
cin >> axisY[i].first;
cin >> axisZ[i].first;
axisX[i].second = axisY[i].second = axisZ[i].second = parent[i] = i;
}
sort(axisX, axisX + N);
sort(axisY, axisY + N);
sort(axisZ, axisZ + N);
for (int i = 0; i < N - 1; i++) {
pq.push({ axisX[i].second, axisX[i + 1].second ,abs(axisX[i].first - axisX[i + 1].first) });
pq.push({ axisY[i].second, axisY[i + 1].second ,abs(axisY[i].first - axisY[i + 1].first) });
pq.push({ axisZ[i].second, axisZ[i + 1].second ,abs(axisZ[i].first - axisZ[i + 1].first) });
}
kruskal();
cout << ans << "\n";
}
'백준' 카테고리의 다른 글
C++ [백준]2630번 색종이 만들기 (0) | 2023.01.11 |
---|---|
C++[백준]17404번 RGB거리 2 (1) | 2023.01.10 |
C++[백준]7579번 앱 (0) | 2023.01.05 |
C++[백준]4386번 별자리 만들기 (2) | 2023.01.05 |
C++[백준]17143번 낚시왕 (2) | 2023.01.04 |