- 4. 迪杰斯特拉算法求最短路径
【问题描述】
在带权有向图G中,给定一个源点v,求从v到G中的其余各顶点的最短路径问题,叫做单源点的最短路径问题。
在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。
请在本题中,读入一个有向图的带权邻接矩阵(即数组表示),建立有向图并参考《耿》教材中算法7.15,编程求出源点至图中每一个其它顶点的最短路径长度。
【输入形式】
输入的第一行依次是2个正整数n和s,表示图中共有n个顶点,且源点编号为s(顶点编号从0~n-1)。其中n不超过50,s小于n。
以后的n行中每行有n个用空格隔开的整数。对于第i行的第j个整数,如果大于0,则表示第i个顶点有指向第j个顶点的有向边,且权值为对应的整数值;如果这个整数为0,则表示没有i指向j的有向边。当i和j相等的时候,对应的整数也是0。
【输出形式】
只有一行,共有n-1个整数,表示源点至其它每个顶点 (编号从小到大顺序) 各自的最短路径长度。如果不存在从源点至相应顶点的路径,则输出-1。
注意: 各输出数据间用1个空格分隔, 行尾输出换行。
【样例输入】
4 1
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0
【样例输出】
6 4 7
【样例说明】
在本题中,需要在计算最短路径的过程中将每个顶点是否可达记录下来(可用非常大的整数来标记不可达),直到求出每个可达顶点的最短路径之后,算法才能够结束。
迪杰斯特拉算法的特点是按照路径长度递增的顺序,依次添加下一条长度最短的边,从而不断构造出相应顶点的最短路径。
#include <bits/stdc++.h>
const int INF = 9999999;
using namespace std;
int arc[505][505];
int n;
int start;
int dis[505];
int s[505] = {0};
void create()
{
cin >> start;
int data;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> data;
if (data)
arc[i][j] = data;
else
arc[i][j] = INF;
}
}
}
int findmin()
{
int min = 2000;
int u = -1;
for (int i = 0; i < n; i++)
{
if (s[i] == 0 && min > dis[i])
{
min = dis[i];
u = i;
}
}
return u;
}
void show()
{
for (int i = 0; i < n; i++)
{
if (dis[i])
{
if (dis[i] < INF)
cout << dis[i] << " ";
else
cout << -1 << " ";
}
}
}
void dijkstra()
{
int min;
for (int i = 0; i < n; i++)
{
dis[i] = INF;
s[i] = 0;
}
dis[start] = 0;
for (int i = 0; i < n; i++)
{
int min = findmin();
if (min == -1)
return;
s[min] = 1;
for (int j = 0; j < n; j++)
{
if (s[j] == 0 && (arc[min][j] != INF) && dis[j] > dis[min] + arc[min][j])
{
dis[j] = dis[min] + arc[min][j];
}
}
}
}
int main()
{
cin >> n;
create();
dijkstra();
show();
}