cs
CS/PS

[BOJ] 4386번 : 별자리 만들기

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

 

4386번: 별자리 만들기

도현이는 우주의 신이다. 이제 도현이는 아무렇게나 널브러져 있는 n개의 별들을 이어서 별자리를 하나 만들 것이다. 별자리의 조건은 다음과 같다. 별자리를 이루는 선은 서로 다른 두 별을 일

www.acmicpc.net

 

아주 기초적인 MST 문제다.

 

별자리들의 좌표를 받아서 별들 사이의 거리를 저장해서 prim's algorithm으로 풀든지 kruskal's algorithm으로 풀던지 하면 된다.

 

나는 kruskal's algorithm으로 풀었다. N이 매우 작기 때문에 시간은 크게 고려하지 않아도 된다.

 

time complexity를 따지자면, $O(N^2 \log{N} * \alpha)$ 정도일듯. 두 node가 연결되었는지 확인하는 과정에서 union-find algorithm을 쓰는데 보통 상수 시간이 걸리지만 최악의 경우 N까지 걸릴 수 있기 때문에 $\alpha$라고 써 놨다.

 

다만, STL priority_queue로 min heap을 구현하는데 원래 좌표까지 저장하려다보니 좀 복잡해진다.. 다른 사람이 짜놓은 깔끔한 코드가 있다면 참조해서 공부해야겠다..

 

#include <queue>
#include <vector>
#include <math.h>
#include <iostream>

using namespace std;

typedef pair<double,pair<int,int>> Route;
typedef struct {
	bool operator()(Route a, Route b) {
		return a.first > b.first;
	}
}RouteComp;


const int MAX_N = 105;
vector<pair<float,float>> star;
priority_queue<Route,vector<Route>,RouteComp> edge;
vector<int> uf_parent;
double cost_sum = 0;
int n;

int uf_find(int a) {
	if(uf_parent[a]==a) return a;
	else return uf_find(uf_parent[a]);
}

void uf_union(int a, int b) {
	int root_a = uf_find(a);
	int root_b = uf_find(b);
	if(root_a == root_b) return;
	uf_parent[root_b] = root_a;
	uf_parent[b] = root_a;
}

bool uf_check() {
	for(int i = 0 ; i< n; i++) {
		if(uf_find(i) != uf_find(0)) 
			return false;
	}
	return true;
}


int main(void) {
	cin.tie(NULL);cout.tie(NULL);ios_base::sync_with_stdio(false);
	
	float temp1,temp2;
	double cost;
	
	cin>>n;
	for(int i = 0; i < n; i ++) {
		cin>>temp1>>temp2;
		star.push_back(make_pair(temp1,temp2));
		uf_parent.push_back(i);
	}
	
	for(int i = 0; i < n; i ++) {
		for(int j = 0; j < n; j++) {
			if(i==j) continue;
			cost = sqrt(pow(star[i].first- star[j].first,2) + pow(star[i].second - star[j].second, 2) );
			edge.push(make_pair(cost, make_pair(i,j)));
		}
	}
	
	while(!edge.empty()) {
		Route current = edge.top();
		edge.pop();
		if(uf_find(current.second.first) == uf_find(current.second.second)) continue;
		cost_sum += current.first;
		uf_union(current.second.first, current.second.second);
		if(uf_check()) break;
	}
	cout<< cost_sum;
	
	return 0;
}

 

이 코드는 내 github에서도 확인할 수 있다.

https://github.com/Jordano-Jackson/PS/blob/main/BOJ/4386/4386.cpp

 

GitHub - Jordano-Jackson/PS: Problem solving

Problem solving. Contribute to Jordano-Jackson/PS development by creating an account on GitHub.

github.com

 

'CS > PS' 카테고리의 다른 글

[BOJ] 3197번 : 백조의 호수  (0) 2022.09.02
[BOJ] 1655번 : 가운데를 말해요  (0) 2022.07.04
[BOJ] 9466, 1202, 14003, 2166  (0) 2021.09.01
[BOJ] 2749번 : 피보나치 수 3  (0) 2021.08.25
[BOJ] 2473번 : 세 용액  (0) 2021.07.31