该算法解决的是图中从单个源点到其他顶点的最短路径问题:
如图,寻找点1到其他顶点的最短路径。
算法思路:
1、先找到距离源点1最近的顶点k(这个距离不一定是直线距离),可推理此时 k点已经找到最短路径。将k并入集合S。
2、当有k并入S后,源点1到各个顶点的最短距离可能发生变化,此时需要更新这些最短距离信息。
3、重复1、2步每次并入一个顶点。
所需的集合:
1、 需要图G,用邻接矩阵表示。
2、需要最短路径表D[n];
3、需要集合final[n],用以表示点是否在集合S内。
代码实现:
#include<iostream>
using namespace std;
#define INFINITY 2147483647
//无向图的表示
class Graph
{
public:
int vexnum;
int** Arcs;
};
//集合final和集合D
bool final[10010];
int D[10010];
//初始化工作
void Init(Graph &MyGraph,int n)
{
//为图动态分配内存
MyGraph.Arcs = new int*[n+1];
for (int i = 0; i <= n; i++)
{
MyGraph.Arcs[i] = new int[n + 1];
}
//将所有的边都初始化为无穷大,并将所有点都排除到集合S外
for (int i = 0; i <= n; i++)
{
for (int j = 0; j <= n; j++)
{
MyGraph.Arcs[i][j] = INFINITY;
}
final[i] = false;
}
}
int main()
{
int n, m;
cin >> n >> m;
Graph MyGraph;
Init(MyGraph, n);
MyGraph.vexnum = n;
//录入边的信息
int a , b;
for (int i = 0; i < m; i++)
{
cin >> a >> b;
cin >> MyGraph.Arcs[a][b];
MyGraph.Arcs[b][a] = MyGraph.Arcs[a][b];
}
//用图G初始化D表,并将源点并入S
D[1] = 0;
final[1] = true;
for (int i = 2; i <= n; i++)
{
D[i] = MyGraph.Arcs[1][i];
}
//每次找到距离源点最近的点并入S,一共有vexnum-1个点需要并
for (int i = 0; i < MyGraph.vexnum-1; i++)
{
//找到S集合外距离源点最近的点,并入S
int min = INFINITY;
int v;
for (int j = 1; j <= MyGraph.vexnum; j++)
{
if (!final[j])
{
if (D[j] < min)
{
v = j;
min = D[j];
}
}
}
final[v] = true;
//更新D表的信息,如果 D[v] + MyGraph.Arcs[v][j] < D[j]
//(其中v为新并入的顶点,j为S集合外的点),则更新D[j]
for (int j = 1; j <= MyGraph.vexnum; j++)
{
if (!final[j])
{
if (D[v] + MyGraph.Arcs[v][j] < D[j])
{
D[j] = D[v] + MyGraph.Arcs[v][j];
}
}
}
}
//
int sum = 0;
for (int i = 1; i <= MyGraph.vexnum; i++)
{
sum += D[i];
}
cout << sum;
system("pause");
}