图论: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;

}

 

posted @ 2022-05-10 16:42  朱朱成  阅读(129)  评论(0编辑  收藏  举报