洛谷 P5994 [PA2014]Kuglarz

(gyh) 催更了
正好刚做了一道题还热乎着,随便更下

思路

一道最小生成树的题目

做完:原来最小生成树还能这么玩.

要想知道每个点有没有球,必须知道所有点的奇偶性。
而知道一个点的奇偶性的方法有两种:

  1. 花费 (c_{i,i}) 的代价直接获得.
  2. 花费 (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 << '
';
  return 0;
}
原文地址:https://www.cnblogs.com/loceaner/p/13518887.html