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

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

算法思想:
分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

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

如图所示,每一边都有一非负权值。求图G到原点s的到t的最短路径。
在这里插入图片描述

// ShortestPaths.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include<queue>

#define inf -1
using namespace std;


template<class Type>
class Graph
{
    friend int main(void);
public:
    void ShortestPath(int t);
private:
    int* prev,//前驱顶点数组n;
        n;
    Type** c,//G的临界矩阵
        * dist;
    int best;
};

template<class Type>
class MinHeapNode
{
    friend Graph<Type>;
public:
    operator int()const { return length; }
    int x[12];
private:
    int i;
    int Pos;
    Type length;
};

MinHeapNode<int> H;

template<class Type>
void Graph<Type>::ShortestPath(int t)
{
    priority_queue<MinHeapNode<Type>> priority;
    MinHeapNode<Type> E;
    E.i = t;
    E.length = 0;
    E.Pos = 1;
    dist[t] = 0;
    while (true)
    {
        for (int j = 1; j <= n; j++)
        {
            if (c[E.i][j] != inf && E.length + c[E.i][j] < dist[j])
            {
                dist[j] = E.length + c[E.i][j];
                prev[j] = E.i;
                E.x[E.Pos] = j;
                E.Pos++;
                MinHeapNode<Type> N;
                N.i = j;
                N.length = dist[j];
                memcpy(N.x, E.x, 12 * sizeof(int));
                N.Pos = E.Pos;
                priority.push(N);
                if (j == n&&best> dist[j])
                {
                    best = dist[j];
                    H = N;
                }
            }
        }
        if (!priority.empty())
        {
            E = priority.top();
            priority.pop();
        }
        else
        {
            break;
        }
    }
}

int main()
{
    Graph<int> graph; 
    graph.c = new int* [12];
    for (int i = 0; i < 12; i++)
        (graph.c)[i] = new int[12];
    for (int i = 0; i < 12; i++)
        for (int j = 0; j < 12; j++)
            (graph.c)[i][j] = inf;

    (graph.c)[1][2] = 2, (graph.c)[1][3] = 3, (graph.c)[1][4] = 4;
    (graph.c)[2][5] = 7, (graph.c)[2][6] = 2, (graph.c)[2][3] = 3;
    (graph.c)[3][6] = 9, (graph.c)[3][7] = 2;
    (graph.c)[4][7] = 2;
    (graph.c)[5][8] = 3, (graph.c)[5][9] = 3;
    (graph.c)[6][9] = 3, (graph.c)[6][7] = 1;
    (graph.c)[7][9] = 5, (graph.c)[7][10] = 1;
    (graph.c)[8][11] = 3;
    (graph.c)[9][11] = 2;
    (graph.c)[10][9] = 2, (graph.c)[10][11] = 2;

    graph.dist = new int[12];
    for (int i = 0; i < 12; i++)
        graph.dist[i] = 10000;
    graph.n = 11;
    graph.prev = new int[12];
    graph.best = 1000;

    graph.ShortestPath(1);
    
    for (int i = 1; i < 12; i++)
        cout << graph.prev[i] << "\t";
    cout << endl;
    for (int i = 1; i < 12; i++)
        cout << graph.dist[i] << "\t";
    cout << endl;


    cout << H.operator int() << endl;
    for (int i = 1; i <= 11; i++)
        cout << H.x[i] << "\t" ;
    cout << endl;
    return 0;
}

  • 0
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值