代码如有不懂的请在评论区评论,看到尽量解答
CV AC 之后麻烦点个赞,谢谢!
#include <bits/stdc++.h>
using namespace std;
struct Tub {
int s, e, c;
};
void init_set(int S[], int size) {
fill(S, S+size, -1);
}
int find_set(int S[], int x) {
while (S[x] > 0) {
x = S[x];
}
return x;
}
void union_set(int S[], int r1, int r2) {
if (r1 == r2) return;
S[r2] = r1;
}
int cmp(const void *a1, const void *a2) {
struct Tub *b1 = (struct Tub*)a1;
struct Tub *b2 = (struct Tub*)a2;
if (b1->c > b2->c) return 1;
if (b1->c < b2->c) return -1;
return 0;
}
int main() {
int m, n;
while (scanf("%d %d", &m, &n) != EOF) {
int cost = 0;
struct Tub *tub = new struct Tub[n];
int *set = new int[m+1](); // 并查集,用于判断居民点是否在同一个集合中
init_set(set, m+1); // 初始化并查集
for (int i = 0; i < n; i++) {
scanf("%d %d %d", &tub[i].s, &tub[i].e, &tub[i].c);
}
// 克鲁斯卡尔算法
// 将输入的管道成本由小到大排序
qsort(tub, n, sizeof(struct Tub), cmp);
// 计算连通的最小成本
for (int i = 0; i < n; i++) {
int r1 = find_set(set, tub[i].s);
int r2 = find_set(set, tub[i].e);
if (r1 != r2) {
union_set(set, r1, r2);
cost += tub[i].c;
}
}
// 判断所给的 可选管道 是否能够使居民点全部连通
// 如何判断?
// 答:判断集合 set 中所有元素是否只有一个根
int cnt = 0;
for (int i = 1; i < m+1; i++) {
if (set[i] == -1) cnt++;
}
if (cnt == 1) {
printf("%d\n", cost);
} else {
printf("?\n");
}
delete[] tub;
delete[] set;
}
return 0;
}