문제
https://www.acmicpc.net/problem/10021
걸린 시간
- 실패
풀이
C++
#include <bits/stdc++.h>
#define INF 1e9
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
struct DisjointSet{
vector<int> parent, rank;
DisjointSet(int n): parent(n), rank(n, 1){
for(int i = 0; i < n; i++)
parent[i] = i;
}
int find(int u) {
if(u == parent[u]) return u;
return parent[u] = find(parent[u]);
}
void merge(int u, int v){
u = find(u); v = find(v);
if(u == v) return;
if(rank[u] > rank[v]) swap(u, v);
parent[u] = v;
if(rank[u] == rank[v]) rank[v]++;
}
};
struct node{
int u, v, cost;
node(int u, int v, int cost){
this->u = u;
this->v = v;
this->cost = cost;
}
};
bool compare(node a, node b){
return a.cost < b.cost;
}
int n, c;
int x[2000], y[2000];
int adj[2000][2000];
int kruskal(){
int ret = 0, cnt = 0;
vector<node> edges;
for(int u = 0; u < n; u++)
for(int v = 0; v < n; v++)
if(adj[u][v] != 0)
edges.push_back(node(u, v, adj[u][v]));
sort(edges.begin(), edges.end(), compare);
DisjointSet sets(n);
for(int i = 0; i < edges.size(); i++){
int cost = edges[i].cost;
int u = edges[i].u;
int v = edges[i].v;
if(sets.find(u) == sets.find(v)) continue;
sets.merge(u, v);
ret += cost;
cnt++;
}
if(cnt == n-1) return ret;
else return -1;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cin >> n >> c;
for(int i = 0; i < n; i++)
cin >> x[i] >> y[i];
memset(adj, 0, sizeof(adj));
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++){
int dist = pow(x[i]-x[j], 2)+pow(y[i]-y[j], 2);
if(dist >= c) adj[i][j] = dist;
}
cout << kruskal();
return 0;
}
최소 스패닝 트리 개념을 모르고 prefix sum 으로 접근했다. 사이클 없이 n개의 field 가 n-1개의 간선으로 연결되도록 하였지만 작은 예제 만으로도 쉽게 반례를 찾을 수 있었다. 인접한 좌표의 개수와 가중치들의 합을 기준으로 정렬도 해 보았지만 한계가 존재했고, 결국 kruskal 알고리즘을 공부하여 해결했다.
'Baekjoon' 카테고리의 다른 글
Baekjoon 17780번 새로운 게임 (0) | 2020.10.19 |
---|---|
Baekjoon 15591번 MooTube (Silver) (0) | 2020.10.19 |
Baekjoon 11967번 불켜기 (0) | 2020.10.14 |
Baekjoon 7575번 바이러스 (0) | 2020.10.14 |
Baekjoon 2533번 사회망 서비스(SNS) (0) | 2020.10.13 |
댓글