您的位置:首页 > 其它

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

2017-09-13 16:07 357 查看
基本介绍

模板题目

代码实现

基本介绍

终于来发堆优化的迪杰斯特拉了 普通的迪杰斯特拉复杂度是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
4000

输出样例:

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: