[问题描述] 给定各村庄和村庄之间可以建设公路的若干条道路的成本,求每村都有公路连通所需要的最低成本。 ·[基本要求] 输入:村落数N和道路数M,随后输入M行对应M条道路,每行包含3个正整数,分别是该条道路直接连通的两个村庄的编号和修建该道路的预算成本,村庄从1~N编号。[基本要求] 输出:使每个村庄都有公路连通所需要的最低成本;如果输入数据不能使所有村庄畅通,则输出-1,表示有些村庄之间没有路连通。 输入第1行表示: 58 1 2 12 有5个村庄,8条公路 第2~9行分别表示8条 公路情况: 例“1 2 12” 表示1号和2号村庄修 通路需要12(万元)。 输出“19”表示连通 5个村庄需要最低成本 为19(万元)。 输入 第一行为5 8 第二行为1 2 12 第三行为1 3 9 第四行为1 4 11 第五行为1 5 3 第六行为2 3 6 第七行为2 4 9 第八行为3 4 4 第九行为4 5 6 输出 19用c语言实现,每行加上注释
时间: 2023-12-30 21:03:14 浏览: 138
c.zip_公路
```c
#include <stdio.h>
#define MAX_N 1000 // 最大村庄数
#define INF 0x3f3f3f3f // 定义无穷大
int n, m; // n表示村庄数,m表示道路数
int f[MAX_N + 1]; // 并查集数组
struct Edge { // 存储边的结构体
int u, v, w;
} e[MAX_N * (MAX_N - 1) / 2 + 1]; // 最多有n*(n-1)/2条边
void init() { // 并查集初始化
for (int i = 1; i <= n; i++) { f[i] = i; }
}
int find(int x) { // 并查集查找
return f[x] == x ? x : (f[x] = find(f[x]));
}
int cmp(const Edge &a, const Edge &b) { // 按边权从小到大排序
return a.w < b.w;
}
int Kruskal() { // Kruskal算法
int ans = 0, cnt = 0;
init(); // 初始化并查集
for (int i = 1; i <= m; i++) { // 按边权从小到大排序
int u = find(e[i].u), v = find(e[i].v), w = e[i].w;
if (u != v) { // 如果不在同一个连通块内
f[u] = v; // 合并连通块
ans += w; // 累加边权
cnt++; // 计数器加1
if (cnt == n - 1) { break; } // 边数已达到n-1,退出循环
}
}
return cnt == n - 1 ? ans : -1; // 如果边数不足n-1,则说明有些村庄不能连通
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) { scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); }
std::sort(e + 1, e + m + 1, cmp); // 排序
int ans = Kruskal(); // 求最小生成树的权值和
printf("%d\n", ans);
return 0;
}
```
阅读全文