【模板】最短路径(Dijkstra 4heap)

  1. 基本介绍
  2. 模板题目
  3. 代码实现

基本介绍

终于来发堆优化的迪杰斯特拉了 普通的迪杰斯特拉复杂度是O(n^2)的 感觉对于数据大的题和弗洛伊德没什么两样吧 但是堆优化后能到O((m+n) log n) 还比较不错 但不能去搞图中有负边权的情况
我的代码采用了大佬Zheng.HT的模板 用c++的STL优先队列实现 不知道为什么代码看起来那么像SPFA 关于STL 的东西也就不多说了 至于make_pair就是两个东西打包吧变成一个 在这个算法中就能便于把点编号和距离一起压进堆中 比较舒服
代码的原理就是用堆来保存原点到其他点的距离并且维护最小值 访问边的时候进行更新 总是感觉和SPFA有比较像的地方

模板题目

题目描述
给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

输入输出格式
输入格式:
第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。
接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。
输出格式:
一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)

输入输出样例
输入样例:
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
输出样例:
0 2 4 3

代码实现



#include<iostream>
#include<cstdio>
#include<cctype>
#include<queue> 
#include<cstring>
#include<string>

    using namespace std;
    #define in = read()
    typedef long long ll;
    const ll size = 1000000 + 10000;

        struct point{   ll next,to,dis;}edge[size];
        priority_queue <pair<ll , ll> , vector<pair<ll , ll> > , greater<pair<ll , ll> > > q;

            ll n,m,s;
            ll site;
            ll head[size],dis[size];
            bool exist[size];

inline ll read(){
        ll num = 0 , f = 1;   char ch = getchar();

        while(!isdigit(ch)){
                if(ch == '-')   f = -1;
                ch = getchar();
        }

        while(isdigit(ch)){
                num = num*10 + ch - '0';
                ch = getchar();
        }

        return num*f;
}

inline void add(ll x,ll y,ll z){
        edge[++site].next = head[x];
        edge[site].to = y;
        edge[site].dis = z;
        head[x] = site;
}

int main(){
        n in;   m in;   s in;
        for(int i=1;i<=m;i++){
                ll x,y,z;   x in;   y in;   z in;
                add(x,y,z);
        }
        for(int i=1;i<=n;i++)   dis[i] = 2147483647;    dis[s] = 0;

        ll u;
        pair<ll , ll> x;
        q.push(make_pair(0,s));
        while(!q.empty()){
                x = q.top();    q.pop();    u = x.second;
                if(exist[u])    continue;
                exist[u] = true;
                for(int i=head[u];i!=0;i=edge[i].next)
                        if(edge[i].dis + dis[u] < dis[edge[i].to]){
                                dis[edge[i].to] = edge[i].dis + dis[u];
                                q.push(make_pair(dis[edge[i].to],edge[i].to));
                        }
        }

        for(int i=1;i<=n;i++)
                printf("%d ",dis[i]);
}


//COYG
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值