题目描述
【问题描述】 已知含有n个顶点的带权连通无向 图,采用邻接矩阵存储,邻接矩阵 以三元组的形式给出,只给出不包 括主对角线元素在内的下三角形部 分的元素,且不包括不相邻的顶点 对。求该连通图的最小生成树的权值
【输入形式】 第一行给出结点个数n和三元组的 个数count,以下每行给出一个三元 组,数之间用空格隔开。
【输出形式】 最小生成树的权值
【样例输入】5 8
2 1 7
3 1 6
3 2 8
4 1 9
4 2 4
4 3 6
5 2 4
5 4 2
【样例输入】18
解题思路
初始化:将起点的距离设置为0,将其他节点的距离设置为无穷大。将所有节点标记为未访问状态。
选择节点:从未访问的节点中选择距离起点最近的节点,将其标记为已访问状态。
更新距离:对于与当前节点相邻的节点,计算从起点到这些节点的距离,并更新它们的距离值。如果新的距离值比原来的距离值更小,则更新距离值。
重复步骤2和3,直到所有节点都被访问过或者目标节点被访问到。
回溯路径:从终点开始回溯,沿着每个节点的最短路径找到起点。
源代码
#include<iostream>
using namespace std;
typedef struct Edge {
int begin, end, weight; //定义边的两个邻接点、权重
}edgenode;
//递归寻找祖先结点
int Find(int *fathers, int n) {
int f = n;
while (fathers[f] > 0)
f = fathers[f];
return f;
}
//建立邻接表
void CreateEdge(edgenode*& node) {
node = new edgenode;
cin >> node->begin >> node->end >> node->weight; //录入两个临界点的序号及边权重
}
//按边权值由小到大排序
void Sort(edgenode* edgelist[], int e) {
for (int i = 0; i < e; i++)
for (int j = 0; j < e - i - 1; j++)
if (edgelist[j]->weight > edgelist[j + 1]->weight)
swap(edgelist[j], edgelist[j + 1]);
}
//迪杰斯特拉算法
void Kruskal(edgenode* edgelist[], int e, int& cnt) {
int fathers[1000];
for (int i = 0; i < e; i++)
fathers[i] = 0;
int bgf, edf;
for (int i = 0; i < e; i++) {
bgf = Find(fathers, edgelist[i]->begin);
edf = Find(fathers, edgelist[i]->end);
if (bgf != edf) { //判断是否为一个连通分量
fathers[edf] = bgf;
cnt += edgelist[i]->weight; //存放权值
}
}
}
int main() {
edgenode* edgelist[1000];
int n, e;
cin >> n >> e;
for (int i = 0; i < e; i++)
CreateEdge(edgelist[i]);
Sort(edgelist, e);
int cnt = 0;
Kruskal(edgelist, e, cnt);
cout << cnt << endl;
return 0;
}
总结
迪杰斯特拉算法(与上一篇博客类似)