홍시홍의 프로그래밍

[백준 2887] 행성 터널 본문

알고리즘 문제풀이/백준

[백준 2887] 행성 터널

홍시홍 2020. 1. 9. 21:35

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

 

2887번: 행성 터널

문제 때는 2040년, 이민혁은 우주에 자신만의 왕국을 만들었다. 왕국은 N개의 행성으로 이루어져 있다. 민혁이는 이 행성을 효율적으로 지배하기 위해서 행성을 연결하는 터널을 만들려고 한다. 행성은 3차원 좌표위의 한 점으로 생각하면 된다. 두 행성 A(xA, yA, zA)와 B(xB, yB, zB)를 터널로 연결할 때 드는 비용은 min(|xA-xB|, |yA-yB|, |zA-zB|)이다. 민혁이는 터널을 총 N-1개 건설해서 모든 행성이 서로 연결되게

www.acmicpc.net

1/6일날 풀었떤 문제

요구사항

1. 모든 행성을 최소의 비용으로 연결(MST)

 

풀이

최소 스패닝 트리 문제이다.

거리는 x, y, z간의 거리 중 제일 최소의 거리이다. 다른 차원의 좌표가 거리에 영향을 끼치지 않는다

3. x, y, z각 각의 거리를 구한 후, 오름차순으로 정렬한다

4. Union-Find로 연결

 

#include <stdio.h>
#include <algorithm>
#include <list>
#include <iostream>
#include <vector>

using namespace std;
struct p{
    int x,y,z,num;
};

bool cmpx(p a, p b){
    return a.x>b.x;
}
bool cmpy(p a, p b){
    return a.y>b.y;
}
bool cmpz(p a, p b){
    return a.z>b.z;
}

p pl[1000000];

struct edge{
    int weight,from,to;
};

bool cmp(edge a, edge b){
    return a.weight>b.weight;
}

vector <edge> ed;

int parent[100000];

int Find(int x)
{
    if(parent[x]==x) return x;
    return parent[x]=Find(parent[x]);
}
void Union(int x, int y)
{
    x = Find(x);
    y = Find(y);
    parent[x]=y;
}
int n;
int main(){
    cin>>n;
    for(int i=0 ; i < n ; i++){
        scanf("%d%d%d",&pl[i].x, &pl[i].y,&pl[i].z);
        pl[i].num=i;
        parent[i]=i;
    }

    sort(pl,pl+n,cmpx);
    for(int i=0 ; i < n-1 ; i++){
        ed.push_back({abs(pl[i].x- pl[i+1].x), pl[i].num, pl[i+1].num});
    }
    sort(pl,pl+n,cmpy);
    for(int i=0 ; i < n-1 ; i++){
        ed.push_back({abs(pl[i].y- pl[i+1].y), pl[i].num, pl[i+1].num});
    }
    sort(pl,pl+n,cmpz);
    for(int i=0 ; i < n-1 ; i++){
        ed.push_back({abs(pl[i].z- pl[i+1].z), pl[i].num, pl[i+1].num});
    }

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

    int ans=0;
    int cnt=0;
    for(int i = ed.size()-1; cnt!=n-1; i--){
        if(Find(ed[i].from) != Find(ed[i].to)){
            cnt++;
            ans+=ed[i].weight;
            Union(ed[i].from, ed[i].to);
        }
        if(cnt==n-1)
            break;
    }
    printf("%d",ans);
    return 0;
}

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 11650] 좌표 정렬하기  (0) 2020.01.09
[백준 1181] 단어 정렬  (0) 2020.01.09
[백준 9938] 방 청소  (0) 2020.01.09
[백준 10775] 공항  (0) 2020.01.09
[백준 10815] 숫자 카드  (0) 2020.01.09
Comments