一、基于各种数据结构的SPFA
以下各个数据均为不卡SPFA的最短路模板:P3371 【模板】单源最短路径(弱化版)的测试时间
1、STL队列:用时: 1106ms / 内存: 8496KB
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 #include<algorithm> 7 #define inf 336860180 8 using namespace std; 9 int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001]; 10 bool vis[500001]; 11 void add(int a,int b,int c) 12 { 13 v[++cnt]=b; 14 w[cnt]=c; 15 nxt[cnt]=head[a]; 16 head[a]=cnt; 17 } 18 void read() 19 { 20 cin>>n>>m>>s; 21 for(int i=1;i<=m;i++) 22 { 23 cin>>x>>y>>z; 24 add(x,y,z); 25 } 26 } 27 void spfa(int s) 28 { 29 memset(dist,20,sizeof(dist)); 30 queue<int>q; 31 q.push(s); 32 vis[s]=1; 33 dist[s]=0; 34 while(!q.empty()) 35 { 36 int t=q.front(); 37 q.pop(); 38 vis[t]=0; 39 for(int i=head[t];i;i=nxt[i]) 40 { 41 int y=v[i]; 42 if(dist[y]>dist[t]+w[i]) 43 { 44 dist[y]=dist[t]+w[i]; 45 if(!vis[y]) 46 { 47 q.push(y); 48 vis[y]=1; 49 } 50 } 51 } 52 } 53 } 54 void pr() 55 { 56 for(int i=1;i<=n;i++) 57 { 58 if(dist[i]!=inf)cout<<dist[i]; 59 else cout<<"2147483647"; 60 cout<<" "; 61 } 62 } 63 int main() 64 { 65 read(); 66 spfa(s); 67 pr(); 68 return 0; 69 }
2、STL栈:用时: 4257ms / 内存: 8536KB(#2,#9,#10TLE)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 #include<stack> 7 #include<algorithm> 8 #define inf 336860180 9 using namespace std; 10 int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001]; 11 bool vis[500001]; 12 void add(int a,int b,int c) 13 { 14 v[++cnt]=b; 15 w[cnt]=c; 16 nxt[cnt]=head[a]; 17 head[a]=cnt; 18 } 19 void read() 20 { 21 cin>>n>>m>>s; 22 for(int i=1;i<=m;i++) 23 { 24 cin>>x>>y>>z; 25 add(x,y,z); 26 } 27 } 28 void spfa(int s) 29 { 30 memset(dist,20,sizeof(dist)); 31 stack<int>q; 32 q.push(s); 33 vis[s]=1; 34 dist[s]=0; 35 while(!q.empty()) 36 { 37 int t=q.top(); 38 q.pop(); 39 vis[t]=0; 40 for(int i=head[t];i;i=nxt[i]) 41 { 42 int y=v[i]; 43 if(dist[y]>dist[t]+w[i]) 44 { 45 dist[y]=dist[t]+w[i]; 46 if(!vis[y]) 47 { 48 q.push(y); 49 vis[y]=1; 50 } 51 } 52 } 53 } 54 } 55 void pr() 56 { 57 for(int i=1;i<=n;i++) 58 { 59 if(dist[i]!=inf)cout<<dist[i]; 60 else cout<<"2147483647"; 61 cout<<" "; 62 } 63 } 64 int main() 65 { 66 read(); 67 spfa(s); 68 pr(); 69 return 0; 70 }
3、模拟栈:用时: 4242ms / 内存: 8508KB(#2,#9,#10TLE)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 #include<stack> 7 #include<algorithm> 8 #define inf 336860180 9 using namespace std; 10 int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],stk[500001],top; 11 bool vis[500001]; 12 void add(int a,int b,int c) 13 { 14 v[++cnt]=b; 15 w[cnt]=c; 16 nxt[cnt]=head[a]; 17 head[a]=cnt; 18 } 19 void read() 20 { 21 cin>>n>>m>>s; 22 for(int i=1;i<=m;i++) 23 { 24 cin>>x>>y>>z; 25 add(x,y,z); 26 } 27 } 28 void spfa(int s) 29 { 30 memset(dist,20,sizeof(dist)); 31 top=1; 32 stk[top]=s; 33 vis[s]=1; 34 dist[s]=0; 35 while(top>0) 36 { 37 int t=stk[top]; 38 top--; 39 vis[t]=0; 40 for(int i=head[t];i;i=nxt[i]) 41 { 42 int y=v[i]; 43 if(dist[y]>dist[t]+w[i]) 44 { 45 dist[y]=dist[t]+w[i]; 46 if(!vis[y]) 47 { 48 stk[++top]=y; 49 vis[y]=1; 50 } 51 } 52 } 53 } 54 } 55 void pr() 56 { 57 for(int i=1;i<=n;i++) 58 { 59 if(dist[i]!=inf)cout<<dist[i]; 60 else cout<<"2147483647"; 61 cout<<" "; 62 } 63 } 64 int main() 65 { 66 read(); 67 spfa(s); 68 pr(); 69 return 0; 70 }
4、STL优先队列:用时: 1377ms / 内存: 8612KB
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 #include<stack> 7 #include<algorithm> 8 #define inf 336860180 9 using namespace std; 10 int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],stk[500001],top; 11 bool vis[500001]; 12 void add(int a,int b,int c) 13 { 14 v[++cnt]=b; 15 w[cnt]=c; 16 nxt[cnt]=head[a]; 17 head[a]=cnt; 18 } 19 void read() 20 { 21 cin>>n>>m>>s; 22 for(int i=1;i<=m;i++) 23 { 24 cin>>x>>y>>z; 25 add(x,y,z); 26 } 27 } 28 void spfa(int s) 29 { 30 memset(dist,20,sizeof(dist)); 31 priority_queue<int>q; 32 q.push(s); 33 vis[s]=1; 34 dist[s]=0; 35 while(!q.empty()) 36 { 37 int t=q.top(); 38 q.pop(); 39 vis[t]=0; 40 for(int i=head[t];i;i=nxt[i]) 41 { 42 int y=v[i]; 43 if(dist[y]>dist[t]+w[i]) 44 { 45 dist[y]=dist[t]+w[i]; 46 if(!vis[y]) 47 { 48 q.push(y); 49 vis[y]=1; 50 } 51 } 52 } 53 } 54 } 55 void pr() 56 { 57 for(int i=1;i<=n;i++) 58 { 59 if(dist[i]!=inf)cout<<dist[i]; 60 else cout<<"2147483647"; 61 cout<<" "; 62 } 63 } 64 int main() 65 { 66 read(); 67 spfa(s); 68 pr(); 69 return 0; 70 }
时间总的来说是这个样子的:STL栈>模拟栈>STL优先队列>STL队列
二、SPFA的优化
SPFA目前常见的优化有3种,分别是:SLF优化,LLL优化,随机优化。
1、SLF优化:
SLF优化采取的策略是开一个双端队列,如果即将入队节点大于队首值就插入前端,否则插入后端。是最常见的也是最好用的SPFA优化方法
用时: 1100ms / 内存: 8512KB
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 #include<algorithm> 7 #define inf 336860180 8 using namespace std; 9 int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],sum; 10 bool vis[500001]; 11 void add(int a,int b,int c) 12 { 13 v[++cnt]=b; 14 w[cnt]=c; 15 nxt[cnt]=head[a]; 16 head[a]=cnt; 17 } 18 void read() 19 { 20 cin>>n>>m>>s; 21 for(int i=1;i<=m;i++) 22 { 23 cin>>x>>y>>z; 24 add(x,y,z); 25 } 26 } 27 void spfa(int s) 28 { 29 memset(dist,20,sizeof(dist)); 30 deque<int>q; 31 q.push_back(s); 32 vis[s]=1; 33 dist[s]=0; 34 while(!q.empty()) 35 { 36 int t=q.front(); 37 q.pop_front(); 38 vis[t]=0; 39 for(int i=head[t];i;i=nxt[i]) 40 { 41 int y=v[i]; 42 if(dist[y]>dist[t]+w[i]) 43 { 44 dist[y]=dist[t]+w[i]; 45 if(!vis[y]) 46 { 47 if(dist[y]<=dist[q.front()])q.push_front(y); 48 else q.push_back(y); 49 vis[y]=1; 50 } 51 } 52 } 53 } 54 } 55 void pr() 56 { 57 for(int i=1;i<=n;i++) 58 { 59 if(dist[i]!=inf)cout<<dist[i]; 60 else cout<<"2147483647"; 61 cout<<" "; 62 } 63 } 64 int main() 65 { 66 read(); 67 spfa(s); 68 pr(); 69 return 0; 70 }
2、LLL优化:
LLL优化也是开一个双端队列,每次去队首看是否大于平均值,大于就插入队尾继续寻找。看起来高大上实际应用不多的SPFA优化
用时: 1114ms / 内存: 8500KB
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 #include<algorithm> 7 #define inf 336860180 8 using namespace std; 9 int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],sum; 10 bool vis[500001]; 11 void add(int a,int b,int c) 12 { 13 v[++cnt]=b; 14 w[cnt]=c; 15 nxt[cnt]=head[a]; 16 head[a]=cnt; 17 } 18 void read() 19 { 20 cin>>n>>m>>s; 21 for(int i=1;i<=m;i++) 22 { 23 cin>>x>>y>>z; 24 add(x,y,z); 25 } 26 } 27 void spfa(int s) 28 { 29 memset(dist,20,sizeof(dist)); 30 deque<int>q; 31 q.push_back(s); 32 vis[s]=1; 33 dist[s]=0; 34 while(!q.empty()) 35 { 36 int t=q.front(); 37 if(dist[t]*q.size()>sum) 38 { 39 q.pop_front(); 40 q.push_back(t); 41 continue; 42 } 43 q.pop_front(); 44 sum-=dist[t]; 45 vis[t]=0; 46 for(int i=head[t];i;i=nxt[i]) 47 { 48 int y=v[i]; 49 if(dist[y]>dist[t]+w[i]) 50 { 51 dist[y]=dist[t]+w[i]; 52 if(!vis[y]) 53 { 54 q.push_back(y); 55 sum+=dist[y]; 56 vis[y]=1; 57 } 58 } 59 } 60 } 61 } 62 void pr() 63 { 64 for(int i=1;i<=n;i++) 65 { 66 if(dist[i]!=inf)cout<<dist[i]; 67 else cout<<"2147483647"; 68 cout<<" "; 69 } 70 } 71 int main() 72 { 73 read(); 74 spfa(s); 75 pr(); 76 return 0; 77 }
3、随机优化:
随机优化就是rand一下,为0插入队首,为1插入队尾,最不靠谱的优化。
用时: 1259ms / 内存: 8516KB
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<ctime> 5 #include<cstring> 6 #include<queue> 7 #include<algorithm> 8 #define inf 336860180 9 using namespace std; 10 int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],sum; 11 bool vis[500001]; 12 void add(int a,int b,int c) 13 { 14 v[++cnt]=b; 15 w[cnt]=c; 16 nxt[cnt]=head[a]; 17 head[a]=cnt; 18 } 19 void read() 20 { 21 cin>>n>>m>>s; 22 for(int i=1;i<=m;i++) 23 { 24 cin>>x>>y>>z; 25 add(x,y,z); 26 } 27 } 28 void spfa(int s) 29 { 30 memset(dist,20,sizeof(dist)); 31 deque<int>q; 32 q.push_back(s); 33 vis[s]=1; 34 dist[s]=0; 35 while(!q.empty()) 36 { 37 int t=q.front(); 38 q.pop_front(); 39 vis[t]=0; 40 for(int i=head[t];i;i=nxt[i]) 41 { 42 int y=v[i]; 43 if(dist[y]>dist[t]+w[i]) 44 { 45 dist[y]=dist[t]+w[i]; 46 if(!vis[y]) 47 { 48 if(rand()%2)q.push_front(y); 49 else q.push_back(y); 50 vis[y]=1; 51 } 52 } 53 } 54 } 55 } 56 void pr() 57 { 58 for(int i=1;i<=n;i++) 59 { 60 if(dist[i]!=inf)cout<<dist[i]; 61 else cout<<"2147483647"; 62 cout<<" "; 63 } 64 } 65 int main() 66 { 67 srand(time(NULL)); 68 read(); 69 spfa(s); 70 pr(); 71 return 0; 72 }
优化后的时间排序:RAND>LLL>朴素>SLF
如果你喜欢我的文章就来个点赞收藏转发关注吧!!!