- 基本介绍
- 模板题目
- 代码实现
基本介绍
终于来发堆优化的迪杰斯特拉了 普通的迪杰斯特拉复杂度是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