克鲁斯卡尔
查看原帖
克鲁斯卡尔
331168
王小强楼主2021/8/16 13:40
#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
#include <functional>
#include <numeric>

using namespace std;

using T = tuple<int, int, int>;

int main(int argc, char const *argv[]) {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n;
  cin >> n;

  // 应该是完全图,n 个顶点有 n * (n - 1) / 2条边
  vector<vector<int>> mat(n, vector<int>(n));
  for (int u = 0; u < n; ++u)
    for (int v = 0; v < n; ++v) cin >> mat[u][v];

  vector<T> edges;
  for (int u = 0; u < n; ++u)
    for (int v = u + 1; v < n; ++v)
      edges.emplace_back(u, v, mat[u][v]);

  sort(begin(edges), end(edges), [](const auto& e1, const auto& e2) {
    return get<2>(e1) < get<2>(e2);
  });

  vector<int> p(n);
  iota(begin(p), end(p), 0);

  // Path Compression
  function<int(int)> find = [&](int x) -> int {
    return p[x] = p[x] ^ x ? find(p[x]) : x;
  };

  auto merge = [&](int u, int v) -> void {
    p[find(u)] = p[find(v)];
  };

  auto isConnected = [&](int u, int v) -> bool {
    return find(u) == find(v);
  };

  int cnt = 0, mst = 0, u, v, w;
  for (const auto& e : edges) {
    u = get<0>(e), v = get<1>(e), w = get<2>(e);
    if (isConnected(u, v)) continue;
    merge(u, v);
    mst += w;
    if (++cnt == n - 1) {
      cout << mst << endl;
      return 0;
    }
  }

  return 0;
}
2021/8/16 13:40
加载中...