코딩테스트/C++

[ 백준 BOJ ] 2887번 - 행성 터널(C++)

최-코드 2024. 4. 17. 22:44

https://www.acmicpc.net/problem/2887

 

2887번: 행성 터널

첫째 줄에 행성의 개수 N이 주어진다. (1 ≤ N ≤ 100,000) 다음 N개 줄에는 각 행성의 x, y, z좌표가 주어진다. 좌표는 -109보다 크거나 같고, 109보다 작거나 같은 정수이다. 한 위치에 행성이 두 개 이

www.acmicpc.net

거리상 가장 가까운 것만 따지면 된다고 생각해서 x,y,z 따로따로 배열을 구한 후 정렬한 다음 각 값끼리 비교 연산해주면 된다고 생각했는데 그저 정렬이니까 값이 차이가 큰 것끼리 인접할 수 있다는 것을 알아차렸다. 마땅한 풀이가 생각이 안 나서 다른 분의 풀이를 보다가 정렬 후 인접한 두 점의 차를 저장하는 배열을 만드는 것을 보고 바로 풀이법을 떠올렸다. x,y,z 각각 인접한 점끼리의 차(가중치)를 배열에 저장하고 이 배열을 정렬 후 union-find로 싸이클이 만들어지는지만 따지면 된다.

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <memory.h>
#include <vector>

#define endl '\n'
#define ll long long
#define pii pair<int, int>
#define cout std::cout
#define maxNum 2100000000

using namespace std;

int N;
vector<pii> planet[3];
int parent[100000];
vector<pair<int, pii>> dist;

int findParent(int node) {
	if (parent[node] == node)
		return node;
	return parent[node] = findParent(parent[node]);
}

void unionParent(int node1, int node2) {
	node1 = findParent(node1);
	node2 = findParent(node2);
	if (node1 > node2) {
		parent[node2] = node1;
	}
	else {
		parent[node1] = node2;
	}
}

bool compare(pii a, pii b) {
	return a.second < b.second;
}

bool compare2(pair<int,pii> a, pair<int,pii> b) {
	return a.first < b.first;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >> N;
	int tmp1, tmp2, tmp3;
	for (int i = 0; i < N; i++) {
		cin >> tmp1 >> tmp2 >> tmp3;
		parent[i] = i;
		planet[0].emplace_back(i, tmp1);
		planet[1].emplace_back(i, tmp2);
		planet[2].emplace_back(i, tmp3);
	}
	sort(planet[0].begin(), planet[0].end(), compare);
	sort(planet[1].begin(), planet[1].end(), compare);
	sort(planet[2].begin(), planet[2].end(), compare);
	int i = 0;
	while (i != N-1) {
		int num1 = maxNum, num2 = maxNum, num3 = maxNum;
		num1 = abs(planet[0][i].second - planet[0][i + 1].second);
		dist.push_back({ num1,{planet[0][i].first,planet[0][i + 1].first} });
		num2 = abs(planet[1][i].second - planet[1][i + 1].second);
		dist.push_back({ num2,{planet[1][i].first,planet[1][i + 1].first} });
		num3 = abs(planet[2][i].second - planet[2][i + 1].second);
		dist.push_back({ num3,{planet[2][i].first,planet[2][i + 1].first} });
		i++;
	}
	sort(dist.begin(), dist.end(), compare2);
	i = 0;
	int ans = 0;
	int n = 0;
	while (n != N - 1) {
		if (findParent(dist[i].second.first) != findParent(dist[i].second.second)) {
			unionParent(dist[i].second.first, dist[i].second.second);
			ans += dist[i].first;
			n++;
		}
		i++;	
	}
	cout << ans << endl;
	return 0;
}