单源最短路径-分支限界法-优先队列式分支限界法-Dijkstra

问题描述:

给定一个带权有向图G = (V, E), 其中每条边的权是非负实数。另外,还给定V中的一个顶点,称为源。现在要计算源到所有其他各定点的最短长度。这里路的长度是指路上各边权之和。这个问题通常成为单源最短路径问题。

解法:

用优先队列式分支限界法,代码核心跟贪心的Dijkstra算法差不多相同,要首先学会使用优先队列的使用。

贪心的Dijkstra算法实现见Dijkstra算法实现

代码:

#include <bits/stdc++.h>
using namespace std;
class MinHeapNode
{
public:
    int id;
    int length; //从起始点 v 到点 id 的距离
public:
    friend bool operator < (const MinHeapNode &a, const MinHeapNode &b)
    {
        return a.length < b.length;
    }
    friend bool operator > (const MinHeapNode &a, const MinHeapNode &b)
    {
        return a.length > b.length;
    }
};
const int max_ = 0x3f3f3f;
int Graph[100][100];
int dist[100];
int pre[100];
int n, m, v;
void OutPutPath(int i)
{
    if(i == pre[i])
    {
        printf("%d", i);
        return;
    }
    else
    {
        OutPutPath(pre[i]);
        printf(" %d", i);
    }
}
void OutPut()
{
    for(int i = 1; i <= n; ++i)
    {
        if(i != v)
        {
            printf("点 %d 到 %d 的最短距离是 %d\n", v, i, dist[i]);
            printf("路径为:");
            OutPutPath(i);
            printf("\n");
        }
    }
}
void ShortestPaths()
{
    priority_queue<MinHeapNode, vector<MinHeapNode>, greater<MinHeapNode> > q; // 小顶堆
    memset(dist, max_, sizeof(dist));
    dist[v] = 0; //不要忘了这里的初始化
    pre[v] = v;
    MinHeapNode cur_p;
    cur_p.id = v;
    cur_p.length = 0;
    q.push(cur_p);
    while(true)
    {
        if(q.empty() == 1)
            break;
        cur_p = q.top(); //取出堆顶的点
        q.pop(); // 在优先队列中删除刚取出的点
//        cout << q.size() << endl;
        for(int i = 1; i <= n; ++i)
        {
            if(Graph[cur_p.id][i] != max_ && (cur_p.length + Graph[cur_p.id][i] < dist[i]))
            {
                dist[i] = cur_p.length + Graph[cur_p.id][i];
                pre[i] = cur_p.id;
                MinHeapNode temp;
                temp.id = i;
                temp.length = dist[i];
                q.push(temp);
            }
        }
    }


}
void InPut()
{
    int x, y, len;
    scanf("%d %d %d", &v, &n, &m);
    memset(Graph, max_, sizeof(Graph));
    for(int i = 1; i <= m; ++i)
    {
        scanf("%d %d %d", &x, &y, &len);
        Graph[x][y] = Graph[y][x] = len;
        //printf("%d\n", i);
    }
}
int main()
{
    InPut();
    ShortestPaths();
    OutPut();
}

测试样例:

《单源最短路径-分支限界法-优先队列式分支限界法-Dijkstra》

输入:

1 5 7
1 2 10
1 5 100
1 4 30
2 3 50
3 5 10
4 3 20

4 5 60

输出:

点 1 到 2 的最短距离是 10
路径为:1 2
点 1 到 3 的最短距离是 50
路径为:1 4 3
点 1 到 4 的最短距离是 30
路径为:1 4
点 1 到 5 的最短距离是 60

路径为:1 4 3 5

运行截图:

《单源最短路径-分支限界法-优先队列式分支限界法-Dijkstra》

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/m0_38015368/article/details/80449014
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞