不会SPFA的同学们看过来
既然dalao们都在打SPFA,我也不会SPFA,所以写个Dijkstra的题解。
首先提醒那些和我一样感觉自己的代码对,刚从P3371 【模板】单源最短路径(弱化版)过来的同学。
这个题的边是无向图!!!
听到大佬说是模板题,我就从P3371直接过来交上了,然后WA掉9个点,,,我改了好长时间,,,才发现QAQ
还有很多大佬告诉我这是一道练SPFA的好题,的确,数据说得过,似乎也没人卡QAQ,但是我觉得那Dijkstra会更方便一些。
其实真的就是道模板题
我在这里细讲一下Dijkstra做法(包括堆优化方法)
1.Dijkstra无优化版
实际上Dijkstra的思想和Floyd的部分思想是一样的,有用到了一个神奇的东西:松弛操作
if(map[i][j]>map[i][k]+map[k][j]) map[i][j]=map[i][k]+map[k][j];
QAQ???完了???
完了。这就是Dijkstra与Floyd的核心思想,Dijkstra就是把时间复杂度降低,范围缩小而已。
(相信都学过Dijkstra)
想必大家也都知道有一个操作,就是寻找最近的点,我们在写的时候是O(n)的。。。
不觉得太慢了吗???
于是我们有了~~~~
2.Dijkstra + 堆优化
不要觉得堆优化十分高大上,实际上只优化了一些最简单而又最费时间的操作。
大家还记得优先队列吗???(堆也行)
#include<queue> priority_queue<int> que;
就是这个东西,可以O(logn)的找到最近的点了QAQ
具体操作看代码吧!QAQ
代码
链式前向星存图(无优化的找不到了,这个只有带堆优化的QAQ,想看无优化的向下翻):
#include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <iostream> #include <map> #include <queue> #include <set> #include <stack> #include <string> #include <vector> using namespace std; #define go(i, j, n, k) for (int i = j; i <= n; i += k) #define fo(i, j, n, k) for (int i = j; i >= n; i -= k) #define rep(i, x) for (int i = h[x]; i; i = e[i].nxt) #define mn 100010 #define inf 1 << 30 #define ll long long #define ld long double #define fi first #define se second #define root 1, n, 1 #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 inline int read(){ int f = 1, x = 0;char ch = getchar(); while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();} while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } inline void write(int x){ if (x < 0)putchar('-');x = -x; if (x > 9)write(x / 10); putchar(x % 10 + '0'); } //This is AC head above... struct edge{ int v, nxt, w; } e[mn<<1]; int h[mn],p; inline void add(int a,int b,int c){ p++; e[p].nxt = h[a]; h[a] = p; e[p].v = b; e[p].w = c; } struct node{ int u,v; bool operator <(const node &b) const{ return u > b.u; } }; /* bool operator <(const node &a,const node &b) { return a.u > b.u; }; */ int n, m, s, t; int dis[mn]; priority_queue<node> q; inline void Dij(int s){ go(i, 0, n, 1) dis[i] = inf; dis[s] = 0; node o; o.u = 0; o.v = s; q.push(o); while (q.size()){ int u = q.top().v; int d = q.top().u; q.pop(); if(d!=dis[u]) continue; rep(i,u){ int v = e[i].v; int w = e[i].w; if (dis[v] > dis[u] + w){ dis[v] = dis[u] + w; node p; p.u = dis[v], p.v = v; q.push(p); } } } } int main(){ n=read(),m=read(),s=read(),t=read(); go(i,1,m,1){ int u = read(), v = read(), w = read(); add(u, v, w); add(v, u, w); } Dij(s); cout << dis[t]; cout << "\n"; return 0; }
vector暴力存图法(和链式前向星没啥区别,这个包括无优化和有优化的)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<queue> #include<vector> using namespace std; #define go(i,j,n,k) for(register int i=j;i<=n;i+=k) #define fo(i,j,n,k) for(register int i=j;i>=n;i-=k) #define mn 110 #define inf 1<<30 #define root 1,n,1 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define ll long long inline int read(){ int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-f;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int kN = 100000+10; const int INF = 2147483647; int s, n, m, k; int d[kN]; vector<pair<int, int> > G[kN]; bool vis[kN]; void dijkstra_naive(int s) { for (int i = 0; i <= n; i++) d[i] = INF; d[s] = 0; for (int i = 1; i <= n; i++) { // find min u, s.t. d[u] < d[i] for all i that vis[i] = false int u = -1; for (int j = 1; j <= n; j++) if (!vis[j]) { if (u == -1 || d[j] < d[u]) { u = j; } } if (u == -1 || d[u] >= INF) break; vis[u] = true; for (int j = 0; j < G[u].size(); j++) { int v = G[u][j].first; int w = G[u][j].second; if (d[v] > d[u] + w) { d[v] = d[u] + w; } } } } void dijkstra(int s) { for (int i = 0; i <= n; i++) d[i] = INF; d[s] = 0; priority_queue<pair<int, int> > q; q.push(make_pair(0, s)); while (q.size()) { int u = q.top().second; q.pop(); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].first; int w = G[u][i].second; if (d[v] > d[u] + w) { d[v] = d[u] + w; q.push(make_pair(-d[v], v)); } } } } int main() { n = read(); m = read(); s = read(); t = read(); go(i,1,m,1){ int u=read(), v=read(), w=read(); pair<int, int> p; p.first = v; p.second = w; G[u].push_back(p) ; p.first = u; p.second = w; G[v].push_back(p) ; } dijkstra_naive(s); //dijkstra(s); cout << d[t]; }
如果有同学想要板子之类的东西,可以看我的博客QAQ,有部分模板代码QAQ