单源最短路径(分支限界)

  • Post author:
  • Post category:其他



优先级:

当前路径长度


剪枝函数:

由于图G中各边的权均非负,所以结点所对应的当前路长也是解空间树中以该结点为根的子树中所有结点对应的路长的一个下界。扩展结点的过程中,一旦发现一个结点的下界不小于当前找到的最短路长,则算法剪去以该结点为根的子树。





数据的存储:

①二维数组

Type G[n][n]

存储邻接矩阵

②数组

Type dist[n]

记录源点到各顶点的距离

③数组

int prev[n]

记录从源到各顶点路径上的前驱顶点


Graph

template <class Type>
class Graph{
    friend void main();
 public:
    void ShortestPaths(int);
 private:
    int n,        //顶点数
        *prev;    //前驱数组
    Type **c,     //邻接矩阵
        *dist;    //最短距离数组
};

堆中顶点类

MinHeapNode

:

template <class Type>
class MinHeapNode{
    friend Graph<Type>;//友元类
public:
    bool operator<(const MinHeapNode& N)const{ return length<N.length; }
private:
    int i;        //顶点编号
    Type length;  //当前路径长度
}

具体算法:

template<class Type>
void Graph<Type> ::ShortestPaths(int v){
    priority_queue< MinHeapNode<Type> > H;
    //初始化
    MinHeapNode<Type> E;
    E.i=v;
    E.length=0;
    dist[v]=0;
    while(true){
        for(int j=1;j<=n;j++){//遍历所有顶点判断是否与i存在边
            if( (c[E.i][j]<inf) && (E.length+c[E.i][j]<dist[j]) ){//如果ij有边,而且经过i到达j的路径比当前更短,更新
                dist[j]=E.length+c[E.i][j];
                prev[j]=E.i;
                //添加新的结点
                MinHeapNode<Type> N;
                N.i=j;
                N.length=dist[j];
                H.push(E);
            }
        }
        if(H.empty())
            break;
        bool found=false;
        while(!H.empty()){
            E=H.top();
            H.pop(); 
            if(E.length==dist[E.i]){//判断是不是最新的结点
                 found=true;   
                 break;
            }
        }
        if(!found) break;
    }
       
}

tips:

  • 这个算法没有对已经求得最短路径的点进行标记,因此可能后续还会访问到(仅仅判断),但是一定不会再次加入活结点表
  • 如果找到更优的路径,要对dist和prev进行更新,但是活结点表中的原来的点不必删除,加入新的结点,以后肯定先访问到所有加入的点中最优的那个



版权声明:本文为qq_43496675原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。