专题四 · 1001

代码及解释

#include <algorithm>
#include <iostream>

//
// kruskal + 并查集 + 边表
//

struct node {
  int from;
  int to;
  int w;
};

node edge[102 * 100];
int parent[102];

bool cmp(node a, node b) {
  if (a.w <= b.w)
    return true;
  return false;
}
//查找已经建完道路的顶点
int find(int a) {
  if (a != parent[a])
    return find(parent[a]);
  else
    return a;
}
int kruskal(int n, int m) {
  std::sort(edge, edge + m, cmp); //将边的权值从小到大排序
  int i, x, y, ans = 0;
  for (i = 0; i < m; i++) {
    x = edge[i].from;
    y = edge[i].to;
    x = find(x);
    y = find(y);
    if (x != y) {
      ans += edge[i].w;
      parent[y] = x;
    }
  }
  return ans;
}

int main() {
  int n, q, k, i, j, m;
  while (std::cin >> n) {
    m = 0;
    for (i = 1; i <= n; i++) {
      for (j = 1; j <= n; j++) {
        std::cin >> k;
        if (i >= j)
          continue; //标记过的不用重复记录
        edge[m].from = i;
        edge[m].to = j;
        edge[m].w = k;
        m++;
      }
    }
    for (k = 1; k <= n; k++)
      parent[k] = k;
    std::cin >> q;
    //将建完的道路的起点和终点都置为相同的起点
    for (k = 1; k <= q; k++) {
      std::cin >> i >> j;
      i = find(i);
      j = find(j);
      parent[j] = i;
    }
    // n个点,m条边
    std::cout << kruskal(n, m) << std::endl;
  }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值