最短路模板(堆優化dijstra + spfa)
阿新 • • 發佈:2022-03-04
/**\ 最短路模板 輸入: n m s t 接下來m行 u, v, w表示u -> v 有一條權值為w的無向邊 input: 3 3 1 2 1 2 3 2 3 4 1 3 5 output: 3 \**/ #include <bits/stdc++.h> using namespace std; #define fi first #define se second #define go continue #define int long long #define PII pair<int, int> #define sf(x) scanf("%lld",&x) #defineytz int _; sf(_); while(_--) #define fory(i,a,b) for(int i = a; i <= b; ++i) #define forl(i,a,b) for(int i = a; i >= b; --i) #define debug(a) cout << #a << " = " << a <<endl; const int N = 1e5 + 10; struct node { int to, w, next; } e[N << 1]; int cnt = 0, head[N]; inlinevoid add_edge(int u, int v, int w) { e[++cnt].to = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt; } inline void init() { cnt = 0; memset(head, -1, sizeof head); } int n, m, s, t; struct v { int x, dis; bool operator < (const v& a) const { returndis > a.dis; //stl預設大頂堆 } }; int dis[N]; bool vis[N]; /**\ dijstra 1、從源點開始每次選取一個離點集距離最近的點t 新增到集合中 2、利用t點對集合中的點進行鬆弛操作,進行更新 3、使用堆進行1找點的操作降低時間複雜度 4、不能在有負邊權的圖中使用 \**/ inline void dijstra(int s, int t) { priority_queue<v> q; memset(dis, 0x3f, sizeof dis); memset(vis, 0, sizeof vis); dis[s] = 0; q.push({s, 0}); while(!q.empty()) { v now = q.top(); q.pop(); if(vis[now.x]) go; vis[now.x] = 1; for(int i = head[now.x] ; i != -1; i = e[i].next) { int y = e[i].to; if(vis[y]) go; if(dis[y] > dis[now.x] + e[i].w) { dis[y] = dis[now.x] + e[i].w; q.push({y, dis[y]}); } } } if(dis[t] > 0x3f3f3f3f) cout << -1; else cout << dis[t]; } /**\ spfa演算法思路: 1、每次迭代,取出隊頭點v,依次列舉從v出發的邊,v->u,設邊的長度為w 判斷dis[v] + w 是否小於dis[u], 小於則更新值, 2、由於s-u的距離變短了,有可能u能改變其他點,使用vis陣列判斷是否在佇列,沒有則放入 3、若一個點的入隊次數超過n,則存在負環 \**/ queue<int> q1; inline void spfa(int s, int t) { memset(dis, 0x3f, sizeof dis); memset(vis, 0, sizeof vis); dis[s] = 0; vis[s] = 1; q1.push(s); while(!q1.empty()) { int x = q1.front(); q1.pop(); vis[x] = 0; for(int i = head[x]; i != -1; i = e[i].next) { int y = e[i].to; if(dis[y] > dis[x] + e[i].w) { dis[y] = dis[x] + e[i].w; if(!vis[y]) { q1.push(y); vis[y] = 1; } } } } if(dis[t] >= 0x3f3f3f3f) cout << -1; else cout << dis[t]; } inline void solve() { init(); sf(n), sf(m), sf(s), sf(t); fory(i, 1, m) { int x, y, z; sf(x), sf(y), sf(z); add_edge(x, y, z); add_edge(y, x, z); } //dijstra(s, t); spfa(s, t); } signed main() { solve(); return 0; }