cgy12306

[백준 BoJ] 2887 - 행성터널 본문

Algorithm/C++

[백준 BoJ] 2887 - 행성터널

cgy12306 2022. 1. 20. 17:34
// 메모리 초과 코드

#include<iostream>
#include<vector>
#include<algorithm>
#include<tuple>
#include<cmath>
using namespace std;
int N;
int parent[100002];

vector<tuple<int, int, int>> star;
vector<tuple<int, int, long long>> nebula;
int Find(int x) {
    if (parent[x] == x) return x;
    return parent[x] = Find(parent[x]);
}
void Union(int a, int b) {
    a = Find(a);
    b = Find(b);
    if (a < b) parent[b] = a;
    else parent[a] = b;
}
void kruscal() {
    long long sum = 0;
    for (auto n : nebula) {
        int a = get<0>(n);
        int b = get<1>(n);
        long long cost = get<2>(n);
        if (Find(a) != Find(b)) {
            sum += cost;
            Union(a, b);
        }
    }
    cout << sum;
}
void difference(int a, int b) {
    long long x = abs(get<0>(star[a]) - get<0>(star[b]));
    long long y = abs(get<1>(star[a]) - get<1>(star[b]));
    long long z = abs(get<2>(star[a]) - get<2>(star[b]));

    nebula.push_back(make_tuple(a, b, min({ x, y, z })));
}
bool cmp(tuple<int, int, long long> a, tuple<int, int, long long> b) {
    return get<2>(a) < get<2>(b);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> N;
    for (int i = 0; i < N; i++) parent[i] = i;

    for (int i = 0; i < N; i++) {
        int x, y, z;

        cin >> x >> y >> z;
        star.push_back(make_tuple(x, y, z));
    }

    for (int i = 0; i < star.size(); i++) {
        for (int j = i + 1; j < star.size(); j++) {
            difference(i, j);
        }
    }

    sort(nebula.begin(), nebula.end(), cmp);
    star.clear();
    kruscal();
}

 

행성의 최대 크기가 100,000이기 때문에 간선은 100,000 * 100,000가 발생할 수 있다. vector를 int형 튜플로 작성했을 때 12byte가 10,000,000,000개 생성되므로 약 111GB가 생성될 수 있다. 그래서 각 x, y, z축별로 오름차순 정렬한 뒤 크루스칼 알고리즘을 이용해 구하면 해결 할 수 있다.

만약 x축별로 연결했지만 어떤 y하나가 더 가까우면 어떡하지라는 생각을 했었지만 parent 배열에 최신화를 하기 때문에 상관 없었다.

 

// https://www.acmicpc.net/problem/2887
// 행성 터널

#include<iostream>
#include<vector>
#include<algorithm>
#include<tuple>
#include<cmath>
using namespace std;
int N;
int parent[100002];

vector<pair<int, int>> X;
vector<pair<int, int>> Y;
vector<pair<int, int>> Z;
vector<tuple<int, int, long long>> nebula;
int Find(int x) {
    if (parent[x] == x) return x;
    return parent[x] = Find(parent[x]);
}
void Union(int a, int b) {
    a = Find(a);
    b = Find(b);
    if (a < b) parent[b] = a;
    else parent[a] = b;
}
void kruscal() {
    long long sum = 0;
    for (auto n : nebula) {
        int a = get<0>(n);
        int b = get<1>(n);
        long long cost = get<2>(n);
        if (Find(a) != Find(b)) {
            sum += cost;
            Union(a, b);
        }
    }
    cout << sum;
}
bool cmp(tuple<int, int, long long> a, tuple<int, int, long long> b) {
    return get<2>(a) < get<2>(b);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> N;
    for (int i = 0; i < N; i++) parent[i] = i;

    for (int i = 0; i < N; i++) {
        int x, y, z;

        cin >> x >> y >> z;
        X.push_back(make_pair(x, i));
        Y.push_back(make_pair(y, i));
        Z.push_back(make_pair(z, i));
    }

    sort(X.begin(), X.end());
    sort(Y.begin(), Y.end());
    sort(Z.begin(), Z.end());

    for (int i = 0; i < N - 1; i++) {
        nebula.push_back(make_tuple(X[i].second, X[i + 1].second, abs(X[i + 1].first - X[i].first)));
        nebula.push_back(make_tuple(Y[i].second, Y[i + 1].second, abs(Y[i + 1].first - Y[i].first)));
        nebula.push_back(make_tuple(Z[i].second, Z[i + 1].second, abs(Z[i + 1].first - Z[i].first)));
    }

    sort(nebula.begin(), nebula.end(), cmp);

    kruscal();
}

'Algorithm > C++' 카테고리의 다른 글

[백준 BoJ] 10217 - KCM Travel  (0) 2022.02.07
[백준 BoJ] 10282 - 해킹  (0) 2022.01.24
[백준 BoJ] 9372 - 상근이의 여행  (0) 2022.01.20
[백준 BoJ] 1774 - 우주신과의 교감  (0) 2022.01.19
[백준 BoJ] 4386 - 별자리 만들기  (0) 2022.01.19
Comments