单源最短路:求一个点到其他所有点的最短距离
所有边权都是正数:
朴素Dijkstra算法:O(n^2) 稠密图(用邻接矩阵存)多用这种 (n是点,m是边)
朴素Dijkstra算法
S:当前已确定最短距离的点
① 初始化距离:dist[1]=0,dist[i] = +无穷
②for i: 0~n
t<----不在S中的,距离最近的点
s<---t
用t更新其它点的距离
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N =510; int n,m; int g[N][N]; //稠密图用邻接矩阵写 int dist[N]; bool st[N]; int dijkstra() { memset(dist,0x3f,sizeof dist); dist[1]=0; for(int i=0;i<n;i++) { int t =-1; for(int j=1;j<=n;j++)//遍历 dist 数组,找到没有确定最短路径的节点中距离源点最近的点t if(!st[j] && (t == -1 || dist[t]>dist[j])) t=j; st[t] = true; for(int j=1;j<=n;j++)//遍历 t 所有可以到达的节点 i dist[j] = min(dist[j], dist[t]+g[t][j]); } if(dist[n] == 0x3f3f3f3f) return -1; return dist[n]; } int main() { ios::sync_with_stdio(false); cin.tie(NULL),cout.tie(NULL); cin>>n>>m; memset(g, 0x3f, sizeof g); //初始化边无穷大 while(m--) { int a,b,c; cin>>a>>b>>c; g[a][b] = min(g[a][b], c); //a和b之间有多条边 只需要保留最短的 } int t = dijkstra(); cout<<t; return 0; }
堆优化版的Dijkstra算法:O(mlogn) 稀疏图(用邻接表存)多用这种
堆的两种实现方式:手写堆;优先队列
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 150010;
typedef pair <int ,int> PII;
int n,m;
int e[N] , ne[N], h[N], W[N], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c)
{
W[idx] = c, e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0,1});
while(heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if(st[ver]) continue;
st[ver] = true;
for(int i = h[ver];i!=-1;i = ne[i])
{
int j = e[i];
if(dist[j]> W[i] + distance)
{
dist[j] = W[i] + distance;
heap.push({dist[j], j});
}
}
}
if(dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL), cout.tie(NULL);
cin>>n>>m;
memset(h, -1, sizeof h);
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
int t = dijkstra();
cout<<t;
return 0;
}