8.2重新温习一些最短路径的基本算法:
提供数据,运行的时候直接粘贴,不需要输入别的值:
5 0 5 4 10 -1 -1 0 -1 3 2 -1 -1 0 2 3 -1 -1 2 0 -1 -1 -1 1 5 0
图形是这样的:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 10;
const int INF = 32767;
int edge[MAXN][MAXN]; //邻接矩阵
int Vex_num; //顶点个数
int path[MAXN]; //记录节点前驱,也就是存储最短路径
int Serve[MAXN]; //已经求出最短路径的节点数组
int dist[MAXN]; //表示从源点到各个顶点的路径长度,在dijkstra算法里面由于是单源求最短,所以只需要一维数组,
//而在floyd里面,需要求多源最短路径,那个时候需要二维数组
void Print_Map() //打印地图
{
cout << "顶点关系如下:\n";
cout << " ";
for (int i = 0; i < Vex_num; i++)
{
printf("%3d ", i);
}
cout << "\n";
for (int i = 0; i < Vex_num; i++)
{
cout << i;
for (int j = 0; j < Vex_num; j++)
{
printf("% 5d ", edge[i][j]);
}
cout << endl;
}
cout << "\n\n";
}
void Find_path() //找最短路径
{
cout << "现在输出从源点出发到其它所有顶点的最短路径:\n";
for (int i = Vex_num - 1; i > 0; i--)
{
int k = i; //找从k到0的最短路径
cout << "从顶点" << "0" << "到顶点" << i << "的路径为:\n";
cout << k;
while (path[k] != k)
{
k = path[k]; //k节点的前一个节点赋值给k,直到path[0]==0;
cout << "->"<<k;
}
cout << "最短路径长度:" << dist[i] << endl;
}
}
void Dijkstra() //求出源点到其它任意点的最短路径,但是注意,源点是固定的,
{
//思路:(1)从顶点集合中找到距离源点最近的一个点
int min_Vex = 0x3f3f3f3f;
int target_min_Vex; //标记找到离源点最近的点的编号
Serve[0] = 1; //这个程序以编号0的点为源点
for (int i = 0; i < Vex_num; i++)
{
if (Serve[i] != 1) //首先要确保这个点(要找的离源点最近的点)没有被放入最短路径集合
{
if (dist[i] < min_Vex)
{
min_Vex = dist[i];
target_min_Vex = i;
}
}
}
Serve[target_min_Vex] = 1; //将其加入最短路径集合Serve
//思路:(2)找到当前离源点最短路径的点,且将其加入serve集合,那么此时我们知道两件事情;
//1,这个被加入到Serve的点到源点的路径就是最后这个点到源点的最短路径,为什么会这样,可以用反证法来说明
//2,由于新点加入,这个时候需要更新dist[],因为新的点的加入使某些没有连通的边产生变化,
for (int i = 0; i < Vex_num; i++)
{
if (Serve[i]==0) //修改没有加入serve的点,加入的已经是最短路径,不能动了。
{
if (edge[target_min_Vex][i] < INF && dist[target_min_Vex] + edge[target_min_Vex][i] < dist[i])
{
dist[i] = dist[target_min_Vex] + edge[target_min_Vex][i];
path[i] = target_min_Vex; //i的前驱节点是target,也就是新加入的节点
}
}
}
Find_path();
}
int main()
{
//以编号为0的点做源点
//首先要将顶点之间的边关系表示出来,可直接初始化。也可以手动输入
//首先确定有多少个顶点
cout << "输入顶点个数:\n";
cin >> Vex_num;
for (int i = 0; i < Vex_num; i++)
for (int j = 0; j < Vex_num; j++)
edge[i][j] = INF;
memset(dist, -1, sizeof(dist));
for (int i = 0; i < Vex_num; i++) //依次输入每个顶点的邻接顶点和他们之间的距离
{
int i_to_j; //点i到点j的距离
for (int j = 0; j < Vex_num; j++)
{
cout << "顶点" << i << "到顶点" << j << "的距离是";
cin >> i_to_j;
if (i_to_j!=-1) //i到j的边如果不连通,就是无穷大,输入用-1来表示
{
edge[i][j] = i_to_j;
}
}
if (i == 0) //初始化dist[]
{
for (int j = 0; j < Vex_num; j++)
{
dist[j] = edge[i][j];
if (edge[i][j] != -1)
path[j] = i;
else
path[j] = -1;
}
}
}
Print_Map(); //打印地图
Dijkstra(); //用dijkstra算法求单源最短路径
return 0;
}