LOADING

加载过慢请开启缓存 浏览器默认开启

k短路 学习笔记

是什么

字面意思
一种用于求解有向图上从某一起点到某一终点的所有可行路径中第 \(k\) 小(大)的算法。

怎么做

首先把模板放在 这里
其实我并不知道还有没有其他应用

A*

注:对于 \(k\) 短路问题,A* 算法的最坏时间复杂度是 \(O(nk \log n)\) 的。虽然 A* 算法可以通过本题原版数据,但可以构造数据,使得 A* 算法在原题的数据范围内无法通过。事实上,存在使用可持久化可并堆的算法可以做到在 \(O((n+m) \log n + k \log k)\) 的时间复杂度解决 \(k\) 短路问题。详情见 OI-Wiki

(摘自 Luogu k短路 模板题的题目背景)

想要直接学 可持久化可并堆 做法的可以跳过这里。

虽然时间复杂度假了,但是依然可以作为 A* 算法的一个入门练习。
这里放一个可以使用 A* 通过的模板题 链接

具体做法

什么,你连 Dijkstra 都不会?那快去学你的入门课(
或者看看 我的

我们在使用 Dijkstra 的堆优版本求解 最短路 问题时,是这样写的:(这里只写了关键代码)

struct node{
    int to,dis;
        friend bool operator < (node n1,node n2){
        return n1.dis>n2.dis;
    }
};

void dij(int s){
    for(int i=1;i<=n;i++) dis[i]=inf;
    dis[s]=0;
    priority_queue<node> q;
    q.push((node){s,0});
    while(!q.empty()){
        int u=q.top().to;
        q.pop();
        if(sure[u]) continue;
        sure[u]=true;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if(sure[v]) continue;
            if(dis[v]>dis[u]+edge[i].val){
                dis[v]=dis[u]+edge[i].val;
                q.push((node){v,dis[v]});
            }
        }
    }
}

我们可以看出,在 Dijkstra 中,每个点最多只会用于一次松弛操作

可持久化可并堆

正解!

可以去看 俞鼎力大牛的课件,其实讲解还是很详细的(?),至少我是从这个原课件看懂的(

那么首先,你至少得会 可并堆(左偏树) 不然从何谈起(
不会也没事,点击链接可以跳转到学习地址(

ps:上面放的是我未来会写的内容 (咕咕咕),在这条 ps 还在的时候,你可以看 这个