SPFA 算法是 bellman 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同
和bellman一样可以用来判断负环
1 int first[N]; 2 struct Edge{ 3 int to; 4 int next; 5 int w; 6 }edge[N]; 7 int cnt=0; 8 void add(int u,int v,int w){ 9 edge[++cnt].to=v; 10 edge[cnt].w=w; 11 edge[cnt].next=first[u]; 12 first[u]=cnt; 13 } 14 int dis[N]; 15 int main(){ 16 ioscin; 17 int n,m,s; 18 cin>>n>>m>>s; 19 memset(dis,127,sizeof(dis)); 20 dis[s]=0; 21 while(m--){ 22 int u,v,w; 23 cin>>u>>v>>w; 24 add(u,v,w); 25 } 26 queue<int>q; 27 int cnt=0; 28 for(!q.empty()){ 29 cnt++; 30 int num=0; 31 int i=q.front(); 32 q.pop(); 33 for(int j=first[i];j!=0;j=edge[j].next){ 34 if(dis[edge[j].to]>dis[i]+edge[j].w){ 35 num++; 36 dis[edge[j].to]=dis[i]+edge[j].w; 37 q.push(edge[j].to); 38 } 39 } 40 if(num==0){ 41 break; 42 } 43 if(cnt>=n){ 44 cout<<"有负环"; 45 } 46 } 47 for(int i=1;i<=n;++i){ 48 cout<<dis[i]<<' '; 49 } 50 return 0; 51 }//spfa优化
flody快速求各点到各点的最短路;
1 int dis[N][N]; 2 int main(){ 3 int n,m; 4 cin>>n>>m; 5 memset(dis,127,sizeof(dis)); 6 while(m--){ 7 int a,b,c; 8 cin>>a>>b>>c; 9 dis[a][b]=c; 10 dis[b][a]=c; 11 } 12 for(int i=1;i<=n;++i){ 13 dis[i][i]=0; 14 } 15 for(int i=1;i<=n;++i){ 16 for(int j=1;j<=n;++j){ 17 for(int k=1;k<=n;++k){ 18 if(dis[i][j]>dis[i][k]+dis[k][j]){ 19 dis[i][j]=dis[i][k]+dsi[k][j]; 20 } 21 } 22 } 23 } 24 return 0; 25 }//floyd
分层图就是多建边,将所有情况全部列出来
1 #include<iostream> 2 using namespace std; 3 #include<cstring> 4 #include<iomanip> 5 #include<vector> 6 #include<cmath> 7 #include<queue> 8 #include<string> 9 #include<algorithm> 10 #include<set> 11 #include<map> 12 #include<stack> 13 #define ll long long 14 #define all(x) (x).begin(), (x).end() 15 #define pb push_back 16 #define pii pair<int, int> 17 #define pll pair<long long, long long> 18 #define mp make_pair 19 #define ioscin ios_base::sync_with_stdio(false);cin.tie(NULL) 20 #define lb lower_bound 21 #define ub upper_bound 22 const int N = 1e6 + 20; 23 int n, m, k; 24 struct Edge { 25 int to; 26 int next; 27 int w; 28 }e[N]; 29 int cnt = 0; 30 int first[N]; 31 void add(int u, int v, int w) { 32 e[++cnt].w = w; 33 e[cnt].to = v; 34 e[cnt].next = first[u]; 35 first[u] = cnt; 36 } 37 int dis[N]; 38 int vis[N]; 39 priority_queue<pii>q; 40 void dijk(int s) { 41 memset(dis, 127, sizeof(dis)); 42 dis[s] = 0; 43 vis[s]=1; 44 q.push(mp(dis[s], s)); 45 while (!q.empty()) { 46 int w = q.top().first; 47 int x = q.top().second; 48 q.pop(); 49 if (dis[x] != w) 50 continue; 51 for (int i = first[x]; i; i = e[i].next) { 52 if (!vis[e[i].to]&&dis[e[i].to] > dis[x] + e[i].w) { 53 dis[e[i].to] = dis[x] + e[i].w; 54 q.push(mp(dis[e[i].to], e[i].to)); 55 } 56 } 57 } 58 } 59 int main() { 60 ioscin; 61 cin >> n >> m >> k; 62 while (m--) { 63 int a, b, c; 64 cin >> a >> b >> c; 65 add(a, b, c); 66 add(b, a, c); 67 for (int i = 1; i <= k; ++i) { 68 add(a + n * i, b + n * i, c); 69 add(b + n * i, a + n * i, c); 70 add(a + (i - 1) * n, b + n * i, c/2); 71 add(b + (i - 1) * n, a + n * i, c/2); 72 }//重点是这一段建边 73 } 74 dijk(1); 75 int ans = dis[n]; 76 for (int i = 1; i <= k; ++i) { 77 ans = min(ans, dis[n+i*n]); 78 } 79 cout << ans << endl; 80 return 0; 81 }
//此题对应洛谷https://www.luogu.com.cn/problem/P4822
浙公网安备 33010602011771号