贪心法求解单源最短路径问题

      利用贪心算法求解单源最短路径问题,最著名的算法是Dijkstra算法,本文便简单介绍一下该算法。

算法整体思想:按各个顶点与源点之间的路径长度的递增次序,生成源点到各个顶点的最短路径。即先求出长度最短的一条路径,再参照它求出长度次短的一条,以此类推,直到从源点到其他各个顶点的最短路径全部求出为止,俗称迪杰斯特拉算法。

算法设计:设源点为u,顶点集合V被分为两部分,S和V-S,其中S中的顶点到源点的最短路径已经确定,V-S中未确定。该算法选用的贪心策略是:每次从V-S集合中选择一个当前离源点的路径最短的顶点,并将其加入集合S中。

求解步骤:

①设置带权邻接矩阵C[][],一维数组dis[]用来存储最短路径长度,一维数组p[]用来存储最短路径中i顶点的前驱顶点,即p[i]的值为i顶点的前驱顶点。记录顶点是否在S集合中的bool类型的数组res[]。若顶点i在集合S中,res[i]=true,反之为false。

②初始化。res[u]=true;  对V-S中的所有顶点x,设置dist[x]= C[u][x]。如果顶点x与源点u相邻,初始化p[x]为u,如果不相邻,也就是C[u][x]= ∞,初始化p[x]为-1。

③在V-S中依照贪心策略来寻找使得dist[x]具有最小值的顶点tv,满足该条件的顶点就是V-S中距离源点u最近的顶点。

④将tv加入S中,即设置res[tv]=true。

⑤如果V-S集合为空,算法结束。否则转步骤⑥。

⑥对集合V-S中的所有与顶点tv相邻的顶点x,更新其到源点的最短路径长度,即如果dist[x] > dist[tv] + C[tv][x],设置dist[x] = dist[tv] + C[tv][x],并设置p[x]=tv。转步骤③。

由此可求得源点u到该有向带权图的其余各个顶点的最短路径及其长度。

构造实例:

《贪心法求解单源最短路径问题》              

  图1      有向带权图G               

   《贪心法求解单源最短路径问题》

表1      邻接矩阵

《贪心法求解单源最短路径问题》

表2       算法求解过程

《贪心法求解单源最短路径问题》

表3       前驱数组p变化情况

代码实现:

#include <iostream>

using namespace std;
void DA (int n,int u,int *dist,int *p,int C[][5])
{
    bool res[n];
    for(int i=0;i<n;i++)
    {
        dist[i]=C[u][i]; //首先将每个顶点到源点的最短距离初始化为从源点出发,到每个顶点的直接距离(没有边的为无穷,可用INT_MAX代替)
        res[i]=false; //全部顶点放到集合V-S中
        if(dist[i]==INT_MAX) //若源点无边到该顶点
        p[i]=-1; //将路径设为-1
        else
        p[i]=u; //否则设为源点
    }
    res[u]=true;
    for(int i=0;i<n;i++)
    {
        int tv =u;
        int temp = INT_MAX;
        for(int j=0;j<n;j++) 
        {
            if((!res[j])&&(dist[j]<temp)) //每次从剩余顶点中找出一个当前距离源点最近的顶点
            {
                temp=dist[j];
                tv=j;
            }
        }
        if(tv==u)break;
        res[tv]=true;//将顶点tv放入S集合中
        for(int j=0;j<n;j++) //每放入S一个顶点,就要将与tv顶点相连的剩余顶点的到源点最短路径更新一下
        {
            if((!res[j])&&(C[tv][j]!=INT_MAX)) 
                if(dist[j]>dist[tv]+C[tv][j])
            {
                dist[j]=dist[tv]+C[tv][j];
                p[j]=tv; //将剩余顶点的路径设为tv
            }
        }
    }
}
int main()
{

    int A[5][5]={ 0,8,32,INT_MAX,INT_MAX,
                  12,0,16,15,INT_MAX,
                  INT_MAX ,29 ,0,INT_MAX,13,
                  INT_MAX,21,INT_MAX,0,7,
                  INT_MAX,INT_MAX,27,19,0 };
                  int dist[5];
                  int p[5];
                  DA(5,0,dist,p,A);
                  for(int i=0;i<5;i++)
                  cout << dist[i] << " "<<p[i]<<endl;
    return 0;
}

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