最短路SPFA
阿新 • • 發佈:2020-10-22
SPFA演算法是對Bellman-ford演算法的優化,
優化的思想:Bellman-ford演算法是遍歷所有邊,對邊進行鬆弛操作,但是如果前一個邊的距離沒有變化,那麼後一個邊的距離也不會變化。通過這個特性,我們可以將變化距離的點存在佇列中,只對這些點的後繼點進行鬆弛操作。
SPFA演算法的時間複雜度為O(m)-O(nm),m為邊數,n為點數,最壞情況與Bellman-ford演算法相同。
給定一個n個點m條邊的有向圖,圖中可能存在重邊和自環, 邊權可能為負數。
請你求出1號點到n號點的最短距離,如果無法從1號點走到n號點,則輸出impossible。
資料保證不存在負權迴路。
輸入格式:
第一行包含整數n和m。
接下來m行每行包含三個整數x,y,z,表示存在一條從點x到點y的有向邊,邊長為z。
輸出格式:
輸出一個整數,表示1號點到n號點的最短距離。
如果路徑不存在,則輸出”impossible”。
資料範圍:
1≤n,m≤1e5
圖中涉及邊長絕對值均不超過10000。
輸入樣例:
3 3 1 2 5 2 3 -3 1 3 4
輸出樣例:
2
模板程式碼:
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespacestd; typedef pair<int,int>pii; const int N=1e5+10; int n,m; int d[N]; int f[N]; vector<pii>v[N]; int spfa() { memset(d,0x3f,sizeof d); d[1]=0; queue<int>q; q.push(1); f[1]=1; while(!q.empty()) { int t=q.front(); q.pop(); f[t]=0;for(int i=0;i<v[t].size();i++) { pii y=v[t][i]; if(d[y.first]>y.second+d[t]) { d[y.first]=y.second+d[t]; if(!f[y.first]) { f[y.first]=1; q.push(y.first); } } } } if(d[n]>0x3f3f3f3f/2) return -1;//存在負權邊 return d[n]; } int main() { scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { int x,y,w; scanf("%d%d%d",&x,&y,&w); v[x].push_back({y,w}); } int k=spfa(); if(k==-1) printf("impossible\n"); else printf("%d\n",k); return 0; }
給定一個n個點m條邊的有向圖,圖中可能存在重邊和自環, 邊權可能為負數。
請你判斷圖中是否存在負權迴路。
輸入格式
第一行包含整數n和m。
接下來m行每行包含三個整數x,y,z,表示存在一條從點x到點y的有向邊,邊長為z。
輸出格式
如果圖中存在負權迴路,則輸出“Yes”,否則輸出“No”。
資料範圍
1≤n≤2000
1≤m≤10000,
圖中涉及邊長絕對值均不超過10000。
輸入樣例:
3 3
1 2 -1
2 3 4
3 1 -4
輸出樣例:
Yes
分析:引入cnt陣列,記錄每個點到點1所需要的邊數,當某個點的cnt邊數大於等於n時,說明,在求1到這個點的路徑上出現了負環。
程式碼:
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int M=1e4+10,N=2e3+10; typedef pair<int,int>pii; int n,m; vector<pii>v[N]; int d[N]; bool f[N]; int cnt[N]; int spfa() { queue<int>q; for(int i=1;i<=n;i++) { d[i]=0x3f3f3f3f; f[i]=1; q.push(i); } while(!q.empty()) { int t=q.front(); q.pop(); f[t]=0; for(int i=0;i<v[t].size();i++) { pii y=v[t][i]; if(d[y.first]>y.second+d[t]) { d[y.first]=y.second+d[t]; cnt[y.first]=cnt[t]+1; if(cnt[y.first]>=n) return true; if(!f[y.second]) { q.push(y.first); f[y.first]=1; } } } } return false; } int main() { scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { int x,y,w; scanf("%d%d%d",&x,&y,&w); v[x].push_back({y,w}); } int k=spfa(); if(k) printf("Yes\n"); else printf("No\n"); return 0; }