第k短路

最短路径

我们都知道了最短路径的求法,单源最短路中我们有dijkstra和spfa

我们也知道,堆优化的dijkstra是最快的,现在附上代码来回顾回顾!

struct dyh_node{
    int num, the_dis;
    bool operator < (const dyh_node &rhs) const {
        return the_dis > rhs.the_dis;
    }
}dyh_h;
priority_queue<dyh_node> first_q;

 堆优化相比普通的dijkstra就快在解决了循环找dis最小的节点!

注意,我们用大跟堆时,写的排序比较的大小要反起来,也就是the_dis > rhs.the_dis 而不是小于

inline void dijkstra(int the_beg, int the_enl){
    memset(vis, 0, sizeof(vis));
    memset(dis, 0x3f, sizeof(dis));
    dis[the_enl] = 0;
    dyh_h.num = the_enl;
    dyh_h.the_dis = 0;
    first_q.push(dyh_h);
    while(!first_q.empty()){
        dyh_node t = first_q.top(), ne;
        first_q.pop();
        if(vis[t.num]){
            continue;
        }
        vis[t.num] = 1;
        for(reg int i = 0; i < _G[t.num].size(); i++){
            if(dis[_G[t.num][i].v] > dis[t.num] + _G[t.num][i].w && !vis[_G[t.num][i].v]){
                dis[_G[t.num][i].v] = dis[t.num] + _G[t.num][i].w;
                ne.num = _G[t.num][i].v;
                ne.the_dis = dis[_G[t.num][i].v];
                first_q.push(ne);
            }
        }
    }
}

 这就是堆优化了!v表示下一个节点,w表示权值。

第k短路

我们现在给出一个结论,我们现在把dijkstra改一改,就可以成功做出第k短路了,现在我们不需要vis 也不需要松弛,一直进行下去,直到第i个节点第k次出队,那么我们就找到了起点到i节点的第k短路了。自然,这个队列是一个普通的队列,不需要有顺序。

然而,这却不是最快的,我们可以用A*来提高速度,我们设h()为当前花费,g()为估计花费!

什么意思,也就是说,我们假设要找s节点到t节点的第k短路,我们现在已经从s节点走到i节点了,然后我们要从i节点走到节点

现在我们从s节点到i节点已经花费了h(),我们估计从i节点到t节点要走g(),这样在众多的i节点中,我们选择h()+g()最少的先进行,这样更快的求出第k短路!如何求g(),我们只需要建立一个反图,从t节点到i节点的最短路,就知道了g()了!

struct _node{
    int h, g, id;
    _node(int H, int dg, int ID){
        h = H;
        g = dg;
        id = ID;
    }
    bool operator < (const _node &rhs) const {
        return h + g > rhs.h + rhs.g;
    }
};
priority_queue<_node> q;
inline int A_star(){
    while(!q.empty()){
        q.pop();
    }
    q.push(_node(0, dis[beg], beg));
    int tot = 0;
    while(!q.empty()){
        _node t = q.top();
        q.pop();
        if(t.id == enl)
            tot ++;
        if(tot >= k){
            return t.h;
        }
        for(reg int i = 0; i < G[t.id].size(); i++){
            q.push(_node(t.h + G[t.id][i].w, dis[G[t.id][i].v], G[t.id][i].v));
        }
    }
    return -1;
}

如果找不到第k短路,我们就直接输出-1!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值