https://codeforces.com/contest/1245/problem/D
도시(최대 2000)마다 좌표, 파워설치비용, 간선연결가중치가 주어진다.
0번도시를 dummy vertex로 두고, 이 도시랑 연결하는 비용을 파워 설치 비용으로 둔 후, 모든 간선을 정렬하여 mst를 수행한다. mst를 뽑을 때 한 쪽 정점이 0번도시라면 그 도시는 파워를 설치한 도시이고, 양쪽 다 0번이 아니라면 두 도시는 연결된 도시이다.
#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int MAX = 2001;
struct Edge {
int u, v;
ll w;
Edge(int u1,int v1, ll w1):u(u1),v(v1),w(w1){}
bool operator <(Edge e) {
return this->w < e.w;
}
};
ll dist(int x1, int y1, int x2, int y2) {
return abs(x1 - x2) + abs(y1 - y2);
}
int uf[MAX];
int find(int a) {
if (uf[a] == -1) return a;
return uf[a] = find(uf[a]);
}
bool merge(int a, int b) {
a = find(a);
b = find(b);
if (a == b) return false;
uf[a] = b;
return true;
}
int main() {
int n; cin >> n;
ll x[MAX], y[MAX], c[MAX], k[MAX];
for (int i = 1; i <= n; i++)
cin >> x[i] >> y[i];
for (int i = 1; i <= n; i++)
cin >> c[i];
for (int i = 1; i <= n; i++)
cin >> k[i];
vector<Edge> e;
for (int i = 1; i <= n; i++) {
e.push_back(Edge(i, 0, c[i]));
for (int j = 1; j <= n; j++) {
if (i == j) continue;
e.push_back(Edge(i, j, (k[i] + k[j]) * dist(x[i], y[i], x[j], y[j])));
}
}
sort(e.begin(), e.end());
ll ans = 0;
vector<int> power_plants;
vector<P> connections;
fill(uf, uf + MAX, -1);
int cnt = 0;
for (int i = 0;; i++) {
if (merge(e[i].u, e[i].v)) {
ans += e[i].w;
if (e[i].v == 0)
power_plants.push_back(e[i].u);
else
connections.push_back({ e[i].u,e[i].v });
if (++cnt == n) break;
}
}
cout << ans << '\n' <<power_plants.size() << '\n';
for (int ctt : power_plants)
cout << ctt << " ";
cout << '\n' << connections.size() << '\n';
for (P ctt : connections)
cout << ctt.first << " " << ctt.second << '\n';
}
생각)
u,v사이에 간선을 만들 때 v의 파워설치 비용보다 간선설치비용이 싼 경우만 간선으로 해서 그 간선들을 정렬한 후, mst를 수행하는 논리로 풀어봤지만, 논리가 약해서 13번 테케를 통과하지 못했다. 아예 invalid한 논리였던 것 같다. 위의 풀이는 editorial을 참고했다. editorial에선 prim's algorithm을 사용했지만 크루스칼로 풀어봤다.
+)
그래프 문제 중 되게 어려워 보이는 문제도 이렇게 더미정점을 추가해서 푸는 문제가 종종 있는 것 같다. 문제풀때마다 유념해야겠다.
'알고리즘 > 코드포스' 카테고리의 다른 글
Educational round #73 D - Make the fence great again (dp) (0) | 2019.11.07 |
---|---|
codeforces #581 div2 C - Anna, Svyatoslav and Maps ( 플로이드 ) (0) | 2019.11.04 |
codeforces #597 div2 C - Constanze's Machine ( 피보나치 , 구현) (0) | 2019.11.03 |
codeforces #591 D - Sequence Sorting (LIS유사, 투포인터, dp) (0) | 2019.11.02 |
codeforces #591 div2 C - Save the Nature (이분탐색) (0) | 2019.11.01 |