简介
Dijkstra算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
无优化复杂度:O(n ^ 2)
那么有O(km)的Spfa算法我们为什么需要Dijkstra算法呢?
因为某些毒瘤出题人会专门设计网格图来卡Spfa算法,使其变为O(m ^ 2)如下方提到的落谷题目。
洛谷:P3371(弱化版) Spfa能过 P4779(标准版)卡Spfa
普通算法
这是Dijkstra的普通算法(无优化)复杂度O(n ^ 2)
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> using namespace std; static const int MAXN = 100005; static const int MAXM = 200005; static const int INF = 2147483647; struct node { int dis; int next; int to; } e[MAXM]; int head[MAXN],cnt,n,m,s; int dis[MAXN]; bool vis[MAXN]; void add(int ,int ,int ); void Init(); void Dijkstra(); int main() { scanf("%d%d%d",&n,&m,&s); for(int i = 1;i <= m;++i) { int from,to,dis; scanf("%d%d%d",&from,&to,&dis); add(from,to,dis); } Dijkstra(); for(int i = 1;i <= n;++i) printf("%d ",dis[i]); return 0; } void add(int from,int to,int dis) { e[++cnt].next = head[from]; e[cnt].to = to; e[cnt].dis = dis; head[from] = cnt; } void Init() { for(int i = 1;i <= n;++i) dis[i] = (i == s ? 0 : INF); } void Dijkstra() { Init(); for(int i = 1;i <= n;++i) { int flag = 214748364,t = -1; for(int j = 1;j <= n;++j) if(!vis[j] && dis[j] < flag) { flag = dis[j]; t = j; } if(t == -1) break; vis[t] = true; for(int j = head[t];j;j = e[j].next) if(!vis[e[j].to]) dis[e[j].to] = min(dis[e[j].to],dis[t] + e[j].dis); } }
堆优化
这是Dijkstra算法的堆优化。复杂度为O(nlogn)
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> using namespace std; static const int MAXN = 100005; static const int MAXM = 200005; static const int INF = 2147483647; struct node { int dis; int next; int to; } e[MAXM]; int head[MAXN],cnt,n,m,s; int dis[MAXN]; bool vis[MAXN]; void add(int ,int ,int ); void Init(); void Dijkstra_Heap(); int main() { scanf("%d%d%d",&n,&m,&s); for(int i = 1;i <= m;++i) { int from,to,dis; scanf("%d%d%d",&from,&to,&dis); add(from,to,dis); } Dijkstra_Heap(); for(int i = 1;i <= n;++i) printf("%d ",dis[i]); return 0; } void add(int from,int to,int dis) { e[++cnt].next = head[from]; e[cnt].to = to; e[cnt].dis = dis; head[from] = cnt; } void Init() { for(int i = 1;i <= n;++i) dis[i] = (i == s ? 0 : INF); } void Dijkstra_Heap() { priority_queue <pair <int ,int > ,vector <pair <int ,int > >,greater <pair <int ,int > > > Q; Init(); Q.push(make_pair(0,s)); while(!Q.empty()) { int u = Q.top().second; Q.pop(); if(vis[u]) continue; vis[u] = true; for(int i = head[u];i;i = e[i].next) { int v = e[i].to; if(dis[v] > dis[u] + e[i].dis) { dis[v] = dis[u] + e[i].dis; if(!vis[v]) Q.push(make_pair(dis[v],v)); } } } }
文章评论