图论:Djskstra算法 求最短路径
Djskstra算法 求最短路径
构建d数组,记录和起点的距离,初始化为无穷大,起点和起点的距离为0,构建邻接边权的二维数组,初始化为无穷大,然后输入边权。并且构建pre数组,记录最短路径的前驱结点,出发点的前驱结点设为0,代表出发点没有前驱结点,也是一会递归输出路径的退出条件。
int w[51][51];//存储边权值
int d[51];//表示从源点s到i的距离
int pre[51];//表示i的前驱点 用于输出路径
int oo = 10000;
cin >> n >> m >> s;
//边权初始化为无穷大
for (i = 1; i <= n; ++i)
for (j = 1; j <= n; ++j)
w[i][j] = oo;
//初始化d
for (int i = 1; i <= n; ++i)
d[i] = oo;
d[s] = 0;//起点到起点的距离为0
for (i = 1; i <= m; ++i)//输入邻接边权
{
cin >> x >> y >> v;
w[x][y] = w[y][x] = v;
}
利用蓝白点思想,构建蓝白点布尔数组blue false代表是蓝点,true代表是白点,这样省的初始化,因为在全局函数定义的bool数组默认为0.然后进行n次循环,就是要遍历这n个结点,定义mins和k,在内层,先要进行一次循环,遍历每一个结点,找到d[]最小的蓝点,mins是用于存储最小值,便于每次比较更新,找到d最小的蓝点,更新k为蓝点的序号。然后一定要把这个找到的蓝点洗白,然后再进行一个并列的循环,通过找到的这个中转点,更新其他蓝点到原点的距离,如果d[中转点]+边权<d[邻接点],就更新d[邻接点],并且更新pre[邻接点]=中转点。
//求最短距离和路径
for (i = 1; i <= n; ++i)
{
//①:找到一个中转点 并洗白
minn = oo, k = 0;//k就是记录找到的中转点
for (j = 1; j <= n; ++j)
{
if (!blue[j] && d[j] < minn)//如果这个点是一个蓝点 并且和起始点距离小于minn
{
//更新中转点
minn = d[j], k = j;
}
}
blue[k] = 1;//把蓝点洗白
//②:通过中转点 更新生于蓝点到原点距离
for (j = 1; j <= n; ++j)
{
if (d[k] + w[k][j] < d[j])//如果通过中转点到原点更快 更新距离
{
d[j] = d[k] + w[k][j];
pre[j] = k;//更新前驱点
}
}
}
打印最短路径的函数:
void print(int i)//递归输出路径
{
if (pre[i])
print(pre[i]);
cout << "->" << i;
}
完整代码:
#include<iostream>
using namespace std;
int w[51][51];//存储边权值
int d[51];//表示从源点s到i的距离
int pre[51];//表示i的前驱点 用于输出路径
bool blue[51];//白点标记
int i, j, k, x, y, v, minn, oo, s, n, m;//s代表起点 n个点 m个边数
void print(int i)//递归输出路径
{
if (pre[i])
print(pre[i]);
cout << "->" << i;
}
int main()
{
oo = 10000;
cin >> n >> m >> s;
//边权初始化为无穷大
for (i = 1; i <= n; ++i)
for (j = 1; j <= n; ++j)
w[i][j] = oo;
//初始化d
for (int i = 1; i <= n; ++i)
d[i] = oo;
d[s] = 0;//起点到起点的距离为0
for (i = 1; i <= m; ++i)//输入邻接边权
{
cin >> x >> y >> v;
w[x][y] = w[y][x] = v;
}
//求最短距离和路径
for (i = 1; i <= n; ++i)
{
//①:找到一个中转点 并洗白
minn = oo, k = 0;//k就是记录找到的中转点
for (j = 1; j <= n; ++j)
{
if (!blue[j] && d[j] < minn)//如果这个点是一个蓝点 并且和起始点距离小于minn
{
//更新中转点
minn = d[j], k = j;
}
}
blue[k] = 1;//把蓝点洗白
//②:通过中转点 更新生于蓝点到原点距离
for (j = 1; j <= n; ++j)
{
if (d[k] + w[k][j] < d[j])//如果通过中转点到原点更快 更新距离
{
d[j] = d[k] + w[k][j];
pre[j] = k;//更新前驱点
}
}
}
for (int i = 1; i <= n; ++i)
{
if (i != s)
{
print(i);
cout << endl;
}
}
return 0;
}