A了

噢莫加纳加加加  •  21小时前


#include <bits/stdc++.h> // 引入 C++ 常用标准库头文件
#define inf 0x3f3f3f3f   // 定义一个很大的数,用来表示“无穷大”
using namespace std;     // 使用标准命名空间,方便直接使用 cin、cout 等
int g[105][105];         // 邻接矩阵,存储图中每两个点之间的边权
int dis[105], n;         // dis 数组记录每个点到当前最小生成树集合的最小边权,n 为节点数量
bool vis[105];           // 标记数组,vis[i] 为 true 表示节点 i 已被加入最小生成树

void prim(int v) {       // Prim 算法函数,v 是起始节点
	vis[v] = 1;          // 将起始节点 v 标记为已访问,表示它进入最小生成树集合
	dis[v] = 0;          // 起始节点到最小生成树集合的距离设为 0
	for (int i = 0; i < n; i++) { // 遍历所有节点
		if (g[v][i] != 0) {       // 如果起始节点 v 到节点 i 有边
			dis[i] = g[v][i];     // 用这条边的权值初始化节点 i 到集合的最小边权
		}
	}
	for (int i = 0; i < n; i++) { // 进行 n 轮扩展,每轮加入一个节点
		int min = inf;            // 初始化当前最小边权为无穷大
		for (int j = 0; j < n; j++) { // 遍历所有节点,寻找未访问节点中 dis 最小的节点
			if (!vis[j] && dis[j] < min) { // 如果节点 j 未访问,且它到集合的距离更小
				min = dis[j];              // 更新当前最小距离
				v = j;                     // 记录当前距离最小的节点编号
			}
		}
		vis[v] = 1;          // 将选出的节点 v 标记为已访问,加入最小生成树集合
		for (int j = 0; j < n; j++) { // 遍历所有节点,更新未访问节点的最小边权
			if (!vis[j] && g[v][j] != 0 && dis[j] > g[v][j]) { // 如果节点 j 未访问,且通过新加入的节点 v 能获得更小的边权
				dis[j] = g[v][j]; // 更新节点 j 到最小生成树集合的最小边权
			}
		}
	}
}

int main() {             // 主函数
	cin >> n;            // 读入节点数量 n
	int sum = 0;         // 用于累加最小生成树的总权值
	memset(dis, inf, sizeof(dis)); // 将 dis 数组初始化为很大的值
	memset(vis, 0, sizeof(vis));   // 将 vis 数组初始化为 0,表示所有节点都未访问
	for (int i = 0; i < n; i++) { // 读入邻接矩阵的每一行
		for (int j = 0; j < n; j++) { // 读入邻接矩阵的每一列
			cin >> g[i][j];           // 读入节点 i 到节点 j 的边权
		}
	}
	int t = 1;           // 选择节点 1 作为 Prim 算法的起点
	prim(t);             // 从节点 1 开始执行 Prim 算法
	for (int i = 0; i < n; i++) { // 遍历所有节点
		sum = sum + dis[i];       // 累加每个节点到最小生成树集合的最小边权
	}
	cout << sum;         // 输出最小生成树的总权值
	return 0;            // 程序正常结束
}

评论:

请先登录,才能进行评论