采取不断访问邻接矩阵的方法不断更新最短路径的单源最短路径算法。
定义:
邻接矩阵G[n][n],存储两两之间的边以及权重
数组s[n],用来判定某个结点是否已经处理过
数组dist[n],用来保存源结点到各各结点的最短路径
假如有一个图
邻接矩阵即为
G[7][7]=
[0,4,6,6,-1,-1,-1
-1,0,1,-1,7,-1,-1
-1,-1,0,-1,6,4,-1
-1,-1,2,0,-1,5,-1
-1,-1,-1,-1,0,-1,6
-1,-1,-1,-1,1,0,8
-1,-1,-1,-1,-1,-1,0]其中的负一表示无边,也可表示为正无穷
s[7]=[0,0,0,0,0,0,0]
dist[7]=[0,0,0,0,0,0,0]
首先将处理数组中的源点置1,表示要处理源点了即s[0]=1
然后我们查看G[0][n]=[0,4,6,6,-1,-1,-1]
那么我们就知道从源点开始能到达1、2、3号结点以及权重
接着我们更新dist,即dist=[0,4,6,6,-1,-1,-1],表示源点到这些点目前的最短路径
接下来我们选取dist中最小取值点的下标(可达的点),即1号点
我们将一号点加入其中,即s[1]=1
查看G[1][n] = [-1,0,1,-1,7,-1,-1]
我们知道1能到达1、2、4以及权重
接着我们更新dist,这时的更新值应该取min(dist[x],G[1][x]+dist[1])此步意义为要不之前就能到,要不经过1到,取最短的内条路径。
接着取dist中最小取值点下标,且该点未被s记录,然后以此类推……
拿一道学校的例题来复习,题目:
这道题是高速路,显然是无向图,那么邻接矩阵必是对称的,代码:
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
int Max = 65535;
int main()
{
int n,c,s,t;
cin>>n>>c>>s>>t;
int *s1 = new int[n]; //创建结点数组
int **G = new int* [n]; //创建邻接矩阵
for(int i = 0; i<n ; i++){
G[i]=new int [n];
}
for(int i = 0;i<c;i++){ //初始化邻接矩阵,权值最小的边保留
int a,b,d;
cin>>a>>b>>d;
if(G[a-1][b-1] && G[a-1][b-1]<d);
else{
G[a-1][b-1]=d;
G[b-1][a-1]=d;
}
}
int *dist = new int [n]; //最短路径距离数组
for(int i = 0;i<n;i++){ //初始化结点数组
s1[i] = 0;
}
for(int i = 0 ; i<n;i++ ){ //对邻接矩阵中未赋值的点设置为距离正无穷
for(int j = 0 ; j < n ;j++)
{
if(!G[i][j])
G[i][j] = Max;
}
}
s1[s-1]=1; //初始化节点位置
for(int i = 0;i<n;i++){
dist[i] = G[s-1][i];
}
for(int i = 0 ;i<n-1;i++)
{
int minpoint_index; //最小值点下标
int minpoint = 20000;
for(int i = 0 ; i<n;i++)
{
if(!s1[i] && dist[i]<minpoint )
{
minpoint = dist[i];
minpoint_index = i;
}
}
s1[minpoint_index] = 1;
for(int i = 0;i<n;i++){
dist[i] = min(G[minpoint_index][i]+dist[minpoint_index],dist[i]);
}
}
cout<<dist[t-1];
}