BOJ/그래프 이론

[C/C++] 백준 - 1774번 : 우주신과의 교감

JWonK 2022. 2. 9. 17:53
728x90
반응형

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

 

1774번: 우주신과의 교감

(1,1) (3,1) (2,3) (4,3) 이렇게 우주신들과 황선자씨의 좌표가 주어졌고 1번하고 4번이 연결되어 있다. 그렇다면 1번하고 2번을 잇는 통로를 만들고 3번하고 4번을 잇는 통로를 만들면 신들과 선자씨끼

www.acmicpc.net

문제

황선자씨는 우주신과 교감을 할수 있는 채널러 이다. 하지만 우주신은 하나만 있는 것이 아니기때문에 황선자 씨는 매번 여럿의 우주신과 교감하느라 힘이 든다. 이러던 와중에 새로운 우주신들이 황선자씨를 이용하게 되었다.

하지만 위대한 우주신들은 바로 황선자씨와 연결될 필요가 없다. 이미 황선자씨와 혹은 이미 우주신끼리 교감할 수 있는 우주신들이 있기 때문에 새로운 우주신들은 그 우주신들을 거쳐서 황선자 씨와 교감을 할 수 있다.

우주신들과의 교감은 우주신들과 황선자씨 혹은 우주신들 끼리 이어진 정신적인 통로를 통해 이루어 진다. 하지만 우주신들과 교감하는 것은 힘든 일이기 때문에 황선자씨는 이런 통로들이 긴 것을  좋아하지 않는다. 왜냐하면 통로들이 길 수록 더 힘이 들기 때문이다.

또한 우리들은 3차원 좌표계로 나타낼 수 있는 세상에 살고 있지만 우주신들과 황선자씨는 2차원 좌표계로 나타낼 수 있는 세상에 살고 있다. 통로들의 길이는 2차원 좌표계상의 거리와 같다.

이미 황선자씨와 연결된, 혹은 우주신들과 연결된 통로들이 존재한다. 우리는 황선자 씨를 도와 아직 연결이 되지 않은 우주신들을 연결해 드려야 한다. 새로 만들어야 할 정신적인 통로의 길이들이 합이 최소가 되게 통로를 만들어 “빵상”을 외칠수 있게 도와주자.

 

 

 

우주신 사이를 연결하는 통로의 최소 거리를 구하는 문제이다. -> 최소 스패닝 트리

우주신과 황선자씨를 노드로 보고 그 사이 거리를 간선으로 취한다. 이미 이어져 있는 노드들은 union-find 알고리즘을 통해 같은 부모로 속하게 한다.

 

우선순위 큐로 최소 간선을 꺼내며 같은 부모가 아니라면 간선을 통해 연결해주고 그 값을 계속해서 더해준다.

모든 노드가 연결될 때까지 수행한다.

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <set>
#include <map> 
#define fastio ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ENDL cout << endl
#define ll long long	
#define ull unsigned long long
#define INF 987654321
#define Mod 1000000
#define endl '\n'
#define pil pair<int,int>

using namespace std;

typedef struct nodeInformation {
	int number;
	int y;
	int x;
};

typedef struct information {
	int node1;
	int node2;
	long double dist;
}information;

struct cmp {
	bool operator()(information lhs, information rhs) {
		return lhs.dist > rhs.dist;
	}
};

int N, M;
int parent[1003];
vector<nodeInformation> pos;
priority_queue<information, vector<information>, cmp> pq;

int getParent(int x) {
	if (x == parent[x]) return x;
	return parent[x] = getParent(parent[x]);
}

bool isSame(int p, int q) {
	p = getParent(p);
	q = getParent(q);

	if (p == q) return true;
	return false;
}

void nodeUnion(int p, int q) {
	p = getParent(p);
	q = getParent(q);

	if (p < q) parent[q] = p;
	else parent[p] = q;
}

double length(ll y1, ll x1, ll y2, ll x2) {
	return sqrt(((y1 - y2) * (y1 - y2)) + ((x1 - x2) * (x1 - x2)));
}

void input() {
	cin >> N >> M;
	for (int i = 1; i <= N; i++) {
		int y, x;
		cin >> y >> x;
		pos.push_back({ i, y, x });
		parent[i] = i;
	}

	for (int i = 0; i < M; i++) {
		int n1, n2;
		cin >> n1 >> n2;
		nodeUnion(n1, n2);
	}
}

void setting_nodeLength() {
	for (int i = 1; i < N; i++) {
		for (int j = i + 1; j <= N; j++) {
			if (parent[i] == parent[j]) continue;
			pq.push({ i, j, double(length(pos[i-1].y, pos[i-1].x, pos[j-1].y, pos[j-1].x)) });
		}
	}
}


void solution() {
	long double answer = 0;
	while (!pq.empty()) {
		information ps = pq.top();
		pq.pop();

		if (isSame(ps.node1, ps.node2)) continue;
		answer += ps.dist;
		nodeUnion(ps.node1, ps.node2);
	}
	cout << fixed;
	cout.precision(2);
	cout << answer << endl;
}

int main() {
	fastio;
	input();
	setting_nodeLength();
	solution();
	 
	return 0;
}
728x90
반응형