基于各种基础数据结构的SPFA和各种优化
一、基于各種數據結構的SPFA
以下各個數據均為不卡SPFA的最短路模板:P3371 【模板】單源最短路徑(弱化版)的測試時間
1、STL隊列:用時:?1106ms / 內存:?8496KB
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> #define inf 336860180 using namespace std; int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001]; bool vis[500001]; void add(int a,int b,int c) {v[++cnt]=b;w[cnt]=c;nxt[cnt]=head[a];head[a]=cnt; } void read() {cin>>n>>m>>s;for(int i=1;i<=m;i++){cin>>x>>y>>z;add(x,y,z);} } void spfa(int s) {memset(dist,20,sizeof(dist));queue<int>q;q.push(s);vis[s]=1;dist[s]=0;while(!q.empty()){int t=q.front();q.pop();vis[t]=0;for(int i=head[t];i;i=nxt[i]){int y=v[i];if(dist[y]>dist[t]+w[i]){dist[y]=dist[t]+w[i];if(!vis[y]){q.push(y);vis[y]=1;}}}} } void pr() {for(int i=1;i<=n;i++){if(dist[i]!=inf)cout<<dist[i];else cout<<"2147483647";cout<<" ";} } int main() {read();spfa(s);pr();return 0; }
2、STL棧:用時:?4257ms / 內存:?8536KB(#2,#9,#10TLE)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<stack> #include<algorithm> #define inf 336860180 using namespace std; int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001]; bool vis[500001]; void add(int a,int b,int c) {v[++cnt]=b;w[cnt]=c;nxt[cnt]=head[a];head[a]=cnt; } void read() {cin>>n>>m>>s;for(int i=1;i<=m;i++){cin>>x>>y>>z;add(x,y,z);} } void spfa(int s) {memset(dist,20,sizeof(dist));stack<int>q;q.push(s);vis[s]=1;dist[s]=0;while(!q.empty()){int t=q.top();q.pop();vis[t]=0;for(int i=head[t];i;i=nxt[i]){int y=v[i];if(dist[y]>dist[t]+w[i]){dist[y]=dist[t]+w[i];if(!vis[y]){q.push(y);vis[y]=1;}}}} } void pr() {for(int i=1;i<=n;i++){if(dist[i]!=inf)cout<<dist[i];else cout<<"2147483647";cout<<" ";} } int main() {read();spfa(s);pr();return 0; }
3、模擬棧:用時:?4242ms / 內存:?8508KB(#2,#9,#10TLE)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<stack> #include<algorithm> #define inf 336860180 using namespace std; int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],stk[500001],top; bool vis[500001]; void add(int a,int b,int c) {v[++cnt]=b;w[cnt]=c;nxt[cnt]=head[a];head[a]=cnt; } void read() {cin>>n>>m>>s;for(int i=1;i<=m;i++){cin>>x>>y>>z;add(x,y,z);} } void spfa(int s) {memset(dist,20,sizeof(dist));top=1;stk[top]=s;vis[s]=1;dist[s]=0;while(top>0){int t=stk[top];top--;vis[t]=0;for(int i=head[t];i;i=nxt[i]){int y=v[i];if(dist[y]>dist[t]+w[i]){dist[y]=dist[t]+w[i];if(!vis[y]){stk[++top]=y;vis[y]=1;}}}} } void pr() {for(int i=1;i<=n;i++){if(dist[i]!=inf)cout<<dist[i];else cout<<"2147483647";cout<<" ";} } int main() {read();spfa(s);pr();return 0; }
4、STL優先隊列:用時:?1377ms / 內存:?8612KB
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<stack> #include<algorithm> #define inf 336860180 using namespace std; int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],stk[500001],top; bool vis[500001]; void add(int a,int b,int c) {v[++cnt]=b;w[cnt]=c;nxt[cnt]=head[a];head[a]=cnt; } void read() {cin>>n>>m>>s;for(int i=1;i<=m;i++){cin>>x>>y>>z;add(x,y,z);} } void spfa(int s) {memset(dist,20,sizeof(dist));priority_queue<int>q;q.push(s);vis[s]=1;dist[s]=0;while(!q.empty()){int t=q.top();q.pop();vis[t]=0;for(int i=head[t];i;i=nxt[i]){int y=v[i];if(dist[y]>dist[t]+w[i]){dist[y]=dist[t]+w[i];if(!vis[y]){q.push(y);vis[y]=1;}}}} } void pr() {for(int i=1;i<=n;i++){if(dist[i]!=inf)cout<<dist[i];else cout<<"2147483647";cout<<" ";} } int main() {read();spfa(s);pr();return 0; }
時間總的來說是這個樣子的:STL棧>模擬棧>STL優先隊列>STL隊列
二、SPFA的優化
SPFA目前常見的優化有3種,分別是:SLF優化,LLL優化,隨機優化。
1、SLF優化:
SLF優化采取的策略是開一個雙端隊列,如果即將入隊節點大于隊首值就插入前端,否則插入后端。是最常見的也是最好用的SPFA優化方法
用時:?1100ms / 內存:?8512KB
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> #define inf 336860180 using namespace std; int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],sum; bool vis[500001]; void add(int a,int b,int c) {v[++cnt]=b;w[cnt]=c;nxt[cnt]=head[a];head[a]=cnt; } void read() {cin>>n>>m>>s;for(int i=1;i<=m;i++){cin>>x>>y>>z;add(x,y,z);} } void spfa(int s) {memset(dist,20,sizeof(dist));deque<int>q;q.push_back(s);vis[s]=1;dist[s]=0;while(!q.empty()){int t=q.front();q.pop_front();vis[t]=0;for(int i=head[t];i;i=nxt[i]){int y=v[i];if(dist[y]>dist[t]+w[i]){dist[y]=dist[t]+w[i];if(!vis[y]){if(dist[y]<=dist[q.front()])q.push_front(y);else q.push_back(y);vis[y]=1;}}}} } void pr() {for(int i=1;i<=n;i++){if(dist[i]!=inf)cout<<dist[i];else cout<<"2147483647";cout<<" ";} } int main() {read();spfa(s);pr();return 0; }
2、LLL優化:
LLL優化也是開一個雙端隊列,每次去隊首看是否大于平均值,大于就插入隊尾繼續尋找。看起來高大上實際應用不多的SPFA優化
用時:?1114ms / 內存:?8500KB
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> #define inf 336860180 using namespace std; int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],sum; bool vis[500001]; void add(int a,int b,int c) {v[++cnt]=b;w[cnt]=c;nxt[cnt]=head[a];head[a]=cnt; } void read() {cin>>n>>m>>s;for(int i=1;i<=m;i++){cin>>x>>y>>z;add(x,y,z);} } void spfa(int s) {memset(dist,20,sizeof(dist));deque<int>q;q.push_back(s);vis[s]=1;dist[s]=0;while(!q.empty()){int t=q.front();if(dist[t]*q.size()>sum){q.pop_front();q.push_back(t);continue;}q.pop_front();sum-=dist[t];vis[t]=0;for(int i=head[t];i;i=nxt[i]){int y=v[i];if(dist[y]>dist[t]+w[i]){dist[y]=dist[t]+w[i];if(!vis[y]){q.push_back(y);sum+=dist[y];vis[y]=1;}}}} } void pr() {for(int i=1;i<=n;i++){if(dist[i]!=inf)cout<<dist[i];else cout<<"2147483647";cout<<" ";} } int main() {read();spfa(s);pr();return 0; }
3、隨機優化:
隨機優化就是rand一下,為0插入隊首,為1插入隊尾,最不靠譜的優化。
用時:?1259ms / 內存:?8516KB
?
#include<iostream> #include<cstdio> #include<cstdlib> #include<ctime> #include<cstring> #include<queue> #include<algorithm> #define inf 336860180 using namespace std; int n,m,s,x,y,z,v[500001],w[500001],head[500001],nxt[500001],cnt,maxx,dist[500001],sum; bool vis[500001]; void add(int a,int b,int c) {v[++cnt]=b;w[cnt]=c;nxt[cnt]=head[a];head[a]=cnt; } void read() {cin>>n>>m>>s;for(int i=1;i<=m;i++){cin>>x>>y>>z;add(x,y,z);} } void spfa(int s) {memset(dist,20,sizeof(dist));deque<int>q;q.push_back(s);vis[s]=1;dist[s]=0;while(!q.empty()){int t=q.front();q.pop_front();vis[t]=0;for(int i=head[t];i;i=nxt[i]){int y=v[i];if(dist[y]>dist[t]+w[i]){dist[y]=dist[t]+w[i];if(!vis[y]){if(rand()%2)q.push_front(y);else q.push_back(y);vis[y]=1;}}}} } void pr() {for(int i=1;i<=n;i++){if(dist[i]!=inf)cout<<dist[i];else cout<<"2147483647";cout<<" ";} } int main() {srand(time(NULL));read();spfa(s);pr();return 0; }
優化后的時間排序:RAND>LLL>樸素>SLF
如果你喜歡我的文章就來個點贊收藏轉發關注吧!!!
轉載于:https://www.cnblogs.com/szmssf/p/11047202.html
總結
以上是生活随笔為你收集整理的基于各种基础数据结构的SPFA和各种优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我面试几乎必问:你设计索引的原则是什么?
- 下一篇: 用JPA在测试的时候无法创建Entity