CSP-迪杰斯特拉和相关变式(UVA - 11374)

这篇博客介绍了迪杰斯特拉算法及其在求解最短路问题中的应用,包括单源最短路和单源最长路的计算。通过实例分析了如何使用C++实现迪杰斯特拉算法,并讨论了如何处理含有正权边的有向有权图。此外,还提出了一个问题情境,涉及经济线和商业线的猫猫快线,求解从起点到终点的最快路径和所需时间。
摘要由CSDN通过智能技术生成

CSP-迪杰斯特拉算法和变形求解最短路问题

知识简述

迪杰斯特拉(Dijkstra)算法,是一种求解正权边单源最短路的常用算法,稍有了解的人都比较熟悉,这里稍作简述Dij算法的实现过程。
1、首先我们要明确在进行迪杰斯特拉算法的过程中要维护的数据:一个小根堆用来存储当前已经更新过的点,一个dis[n]数组用来存储源点s到其他点的最短距离,一个vis[n]记录每个点是否被更新过。
2、现在开始算法的具体步骤:将dis[n]全部置为inf(极大值),dis[s]=0;将s点放入空的小根堆,并置vis[s]=1。
3、每次从小根堆中取出根元素a(最小值),并遍历该点的邻接边,如果对某个点y和边w(a,y),有dis[y]>dis[a]+w(a,y),则说明该点可以更新,一般在迪杰斯特拉算法中将更新的操作成为松弛,某个点被松弛要完成两个操作:更新dis[y]和将y加入小根堆中。
4、重复操作3,直至小根堆为空。遍历dis[n]数组,其值即为最短路距离,如果有点其dis[]值仍为inf,说明该点不可达。
迪杰斯特拉的算法特点:由于所有边均为正边,由此有如果堆先后弹出了a和b点,则一定有dis[a]<=dis[b],因此不可能存在dis[b]+正边<dis[a]。这个特点可以总结为Dij算法最显著的特征:所有点只会被弹出一次,且只要某个点被弹出,说明到该点的距离已经是最小值。
具体实现:在使用Dij过程中,用到了小根堆数据结构,但考虑到小根堆的初始化比较复杂,可以使用大根堆,将(-dis[i])传入大根堆即可起到与小根堆相同的效果。
拓展:单源正值最长路Dij做法
Dij由于其松弛的性质,也可以用来计算单源最长路,但有几个tips需要注意:
1、计算最长路,松弛操作应该变为dis[y]<dis[a]+w(a,y),且存储点集使用大根堆
2、在最长路的计算时,已经不再满足只要某个点被弹出,说明到该点的距离已经是最大值这条性质,每个点可以被多次弹出。
3、由于在计算最长路时,每个点会被多次弹出,这时有可能出现无意义的更新,为了提高Dij的性能,在出现堆顶x距离<dis[x],说明该点已经被其他更新过,不是最长路了,因此更新无意义,可以直接剪枝去除。
Dijkstra基本实现(C++)

const int inf=1e8;
const int M=1e6;
const int N=1e5;
struct Edge
{
   
    int to,nxt,value;
}e[M];

int head[N];
int tot=1;
int dis[N];
int n;//点数
int m;//边数
void init(int num)
{
   
    for(int i=1;i<=num;i++)
    head[i]=-1;
}
void add(int x,int y,int value)
{
   
    tot++;
    e[tot].to=y;
    e[tot].value=value;
    e[tot].nxt=head[x];
    head[x]=tot;
}
priority_queue<pair<int,int>> q;
void dijkstra(int s)
{
   
    while(q.size()) q.pop();
    //初始化
    for(int i=1;i<=n;I++)
    vis[i]=0,dis[i]=inf;
    dis[s]=0;
    q.push(make_pair(0,s));
    //初始化堆和访问数组
    while(q.size())
    {
   
        int x=q.top().second;
        q.pop();
        //每个点只能被弹出一次
        //在dijkstra的最
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值