洛谷 P5994 [PA2014]Kuglarz
被 \(gyh\) 催更了
正好刚做了一道题还热乎着,随便更下
思路
一道最小生成树的题目
做完:原来最小生成树还能这么玩.
要想知道每个点有没有球,必须知道所有点的奇偶性。
而知道一个点的奇偶性的方法有两种:
- 花费 \(c_{i,i}\) 的代价直接获得.
- 花费 \(c_{l,r}\) 和 \(c_{l,r+1}\) 的代价获得 \(r+1\) 点处的代价.
最后的目的就是使每个点都能访问到。
所以可以建边,求最小生成树。
因为题目给出的是点权,所以将 \(i - 1\) 和 \(j\) 连边,边权为 \(c_{i,j}\),然后求最小生成树即可。
代码
/*
Author:loceaner
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
const int A = 2e3 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int cnt, tot, n, fa[A];
struct qwq { int x, y, val; } a[B];
inline int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
bool cmp(qwq a, qwq b) {
return a.val < b.val;
}
signed main() {
n = read();
for (int i = 1; i <= n; i++) {
fa[i] = i;
for (int j = i; j <= n; j++)
a[++tot].x = i - 1, a[tot].y = j, a[tot].val = read();
}
sort(a + 1, a + 1 + tot, cmp);
int ans = 0;
for (int i = 1; i <= tot; i++) {
int x = a[i].x, y = a[i].y;
int dx = find(x), dy = find(y);
if (dx != dy) {
cnt++;
fa[dx] = dy;
ans += a[i].val;
}
if (cnt == n) break;
}
cout << ans << '\n';
return 0;
}
转载不必联系作者,但请声明出处