Problem Description
在带权有向图G中,给定一个源点v,求从v到G中的其余各顶点的最短路径问题,叫做单源点的最短路径问题。
在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。
可将迪杰斯特拉算法描述如下:
在本题中,读入一个有向图的带权邻接矩阵(即数组表示),建立有向图并按照以上描述中的算法求出源点至每一个其它顶点的最短路径长度。
Input Description
输入的第一行包含2个正整数n和s,表示图中共有n个顶点,且源点为s。其中n不超过50,s小于n。
以后的n行中每行有n个用空格隔开的整数。对于第i行的第j个整数,如果大于0,则表示第i个顶点有指向第j个顶点的有向边,且权值为对应的整数值;如果这个整数为0,则表示没有i指向j的有向边。当i和j相等的时候,保证对应的整数为0。
Output Description
只有一行,共有n-1个整数,表示源点至其它每一个顶点的最短路径长度。如果不存在从源点至相应顶点的路径,输出-1。
请注意行尾输出换行。
Sample Input
4 1
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0
Sample Output
6 4 7
Hint
在本题中,需要按照题目描述中的算法完成迪杰斯特拉算法,并在计算最短路径的过程中将每个顶点是否可达记录下来,直到求出每个可达顶点的最短路径之后,算法才能够结束。
迪杰斯特拉算法的特点是按照路径长度递增的顺序,依次添加下一条长度最短的边,从而不断构造出相应顶点的最短路径。
另外需要注意的是,在本题中为了更方便的表示顶点间的不可达状态,可以使用一个十分大的值作为标记。
我的想法:
我的代码:
#include <iostream>
using namespace std;
#define MAX 50
#define INF 99999999
int n, s;
int str[MAX][MAX];
int longth[MAX];
bool visited[MAX];
int main()
{
cin >> n >> s;
//初始化数组
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
scanf("%d", &str[i][j]);
}
visited[i] = false;
}
//将第s行数组的数据装到longth中表示s到各个顶点之间的距离
for (int i = 0; i < n; i++)
{
longth[i] = str[s][i];
if (longth[i] == 0 && i != s)
{
longth[i] = INF;
}
}
//s访问了
visited[s] = true;
int min;
int v;
v = s;
for (int i = 0; i < n; i++)
{
min = INF;
//寻找最小的那个值
for (int j = 0; j < n; j++)
{
if (min > longth[j] && visited[j] == false)
{
min = longth[j];
v = j;
}
}
visited[v] = true;
for (int j = 0; j < n; j++)
{
if (visited[j] == false && longth[j] > str[v][j] + longth[v] && str[v][j] != 0)
{
longth[j] = str[v][j] + longth[v];
}
}
/*for (int j = 0; j < n; j++)
{
cout << longth[j] << " ";
}
cout << endl;*/
}
for (int i = 0; i < n; i++)
{
if (i != s)
{
if (longth[i] == INF)
{
cout << -1 << " ";
}
else
{
cout << longth[i] << " ";
}
}
}
cout << endl;
return 0;
}