#include <stdio.h> const int N0=30; const int INF=10000; //不连通的城镇之间的距离==无穷大 int a[N0+1][N0+1]; //n个城镇之间的距离数据(不连通的城镇之间的距离=INF) int n; //n-城镇的数目(即矩阵的阶数) /*读入城镇的数目(即矩阵的阶数)n */ void readData(){ int i,j; //i,j-循环变量 scanf("%d", &n); //读入矩阵阶数n for( i=1; i<=n; i++){ for( j=1; j<=n; j++){ scanf("%d", &a[i][j]); //读入城镇i到城镇j的距离:a[i][j] if( i!=j && a[i][j]==0 ){//若城镇不连通,则距离a[i][j]=INF a[i][j] = INF; } } } } /* 以x为起始节点,遍历x所在的连通分支G,根据G中节点的数目 判断 n个城镇是否是连通 */ void WFS( int x ){ int q[N0+1], f, r; //以x为起始遍历节点(城镇)的连通分支G中 未遍历邻居的节点(城镇)队列; f-队头位置下标; r-对尾位置下标; int mark[N0+1]={ 0 }; //mark[]-n个节点是否已经遍历的标志(元素都初始化为0) int j, num=0; //j-列下标(循环变量); num-以x为起始遍历节点的连通分支G 中节点的数目 mark[x] = 1; //城镇x(首节点)进入连通分支G中(已遍历过) num++; //以x为起始遍历节点的连通分支G中节点的数目+1 //(1)遍历以x为起始节点的连通分支G,计算此连通分支中节点的数目num //***************************************************************************************** //========================================================================================= //(2)根据连通分支内城镇的数目num,判断n个城镇是否连通 if( num == n ){ //n个城镇连通 printf("Yes\n"); }else{ //n个城镇‘不’连通 printf("No\n"); } } int main(){ FILE *fp; if((fp=fopen("dist.in", "r")) != NULL ){ fclose(fp); //存在的话,要先把之前打开的文件关掉 freopen("dist.in", "r", stdin); freopen("dist.out", "w", stdout); } readData(); //读取城镇距离数据 WFS( 1 ); //以节点1 为起始,判断 n个城镇是否是连通 return 0; }
时间: 2023-12-04 07:06:06 浏览: 63
这段代码实现了一个以邻接矩阵表示的图的连通性判断,主要功能包括读取城镇之间的距离数据,以及判断这些城镇是否连通。具体实现如下:
1. 首先定义了邻接矩阵a[N0+1][N0+1],用于存储n个城镇之间的距离数据。
2. 读取城镇的数目n和城镇之间的距离数据,若城镇不连通,则将距离设为INF(即无穷大)。
3. 定义了WFS函数,以x为起始节点,遍历x所在的连通分支G,并根据G中节点的数目判断n个城镇是否连通。
4. 在WFS函数中,使用队列q[N0+1]来存储未遍历邻居的节点,mark[N0+1]数组用于记录节点是否已经遍历的标志。
5. WFS函数中的核心部分为遍历以x为起始节点的连通分支G,计算此连通分支中节点的数目num。
6. 在计算完num之后,根据连通分支内城镇的数目num,判断n个城镇是否连通。
7. 最后,在main函数中调用readData函数读取城镇距离数据,调用WFS函数以节点1为起始,判断n个城镇是否连通。
注意,该代码中的城镇距离数据是从文件中读取的,文件名为“dist.in”,输出结果也是写入文件“dist.out”中。
相关问题
#include <stdio.h> #include<algorithm> #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; }是什么结构体.使用这种结构体要么相比其他结构体有什么好处
这段代码中的结构体是Edge,用来存储图的边。使用Edge结构体的好处是可以将一条边的信息(起点、终点和权值)封装在一个结构体中,方便在排序和查找等操作中进行处理。此外,定义结构体类型还可以使代码更加清晰易懂,提高代码的可读性和可维护性。同时,由于Edge结构体只包含三个元素,相比其他结构体类型,它的内存占用较小,可以减少空间的浪费。
#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;}电脑显示sort不属于std请改正
可以将 `std::sort` 改为 `sort`,因为 `sort` 函数在 `<algorithm>` 头文件中定义,所以不需要加上 `std::` 前缀。修改后的代码如下:
```cpp
#include <stdio.h>
#include <algorithm>
#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;
}
```
阅读全文