众所周知,SPFA死了
一种神奇的Dijkstra,用node.min_dis!=dis[top]判断是否入队,实测比正常的Dijkstra快得多
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=3000000; const int M=6000000; struct Edge{ int next,to,w; }e[M<<1]; int ecnt,head[MAXN]; inline void adds(int x,int y,int w){ e[++ecnt].next = head[x]; e[ecnt].to = y; e[ecnt].w = w; head[x] = ecnt; } struct Node{ int id,w; Node(int x=0,int y=0){id=x;w=y;} bool operator < (const Node &rhs) const { return w>rhs.w; } }top; priority_queue<Node> Q; int dis[MAXN],vis[MAXN]; void dij(int s){ memset(dis,0x3f,sizeof(dis)); Q.push(Node(s,0));dis[s]=0; while(!Q.empty()){ top=Q.top();Q.pop(); int mnid=top.id,mn=top.w; if(vis[mnid]) continue; if(mn!=dis[mnid])continue;vis[mnid]=1; for(int i=head[mnid];i;i=e[i].next){ int v=e[i].to; if(dis[v]>dis[mnid]+e[i].w){ dis[v]=dis[mnid]+e[i].w; Q.push(Node(v,dis[v])); } } } } int n,m,s; int main(){ cin>>n>>m>>s; for(int i=1;i<=m;i++){ int x,y,w; x=rd();y=rd();w=rd(); adds(x,y,w); } dij(s); for(int i=1;i<=n;i++){ printf("%d ",dis[i]); } return 0; }
SPFA 除了负权边、负环、费用流,最好不用
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #define MAXN 500005 using namespace std; int m,n,st; int dis[MAXN]; int cnode[MAXN]; int head[MAXN],cnt; bool sta[MAXN]; struct Edge{ int to,next,w; }e[MAXN]; void add(int x,int y,int w){ e[++cnt].to = y; e[cnt].w = w; e[cnt].next = head[x]; head[x]=cnt; } queue<int> Q; bool spfa(int st){ Q.push(st); sta[st]=1; int r; while(!Q.empty()){ r=Q.front(); Q.pop(); sta[r]=0; for(int i=head[r];i!=-1;i=e[i].next){ if(dis[e[i].to]>dis[r]+e[i].w){ dis[e[i].to]=dis[r]+e[i].w ; if(!sta[e[i].to]){ Q.push(e[i].to ); sta[e[i].to ]=1; cnode[e[i].to]++;//同下 if(cnode[e[i].to]>n) return 0;//判负环 } } } } } int main(){ memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&st); // cin>>n>>m>>st; int x,y,w; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&w); // cin>>x>>y>>w; add(x,y,w); } for(int i=1;i<=n;i++) dis[i]=2147483647; dis[st]=0; spfa(st); for(int i=1;i<=n;i++) cout<<dis[i]<<" "; }
dijkstra 手写堆优化
这个倒是不慢,就是不好写
#include<iostream> #include<cstdio> #include<cstring> #define MAXN 500005 using namespace std; struct Node{ int id,w; }node,r; Node hp[MAXN*2+5]; long long size; inline void pus(long long id,long long w){ r.id=id; r.w = w; hp[++size]=r; int now=size; while(now>1){ if(hp[now>>1].w <=hp[now].w ) break; swap(hp[now>>1],hp[now]); now>>=1; } } inline void del(){ hp[1]=hp[size--]; int now=1,next; while(now<<1<=size){ next=now<<1; if(next<size&&hp[next].w >hp[next+1].w ) next++; if(hp[next].w >=hp[now].w ) break; swap(hp[next],hp[now]); now=next; } } int head[MAXN],cnt; long long dis[MAXN]; bool vis[MAXN]; struct Edge{ int from,to,next,w; }e[MAXN*2]; inline void add(int x,int y,int w){ e[++cnt].from = x; e[cnt].to = y; e[cnt].w =w; e[cnt].next = head[x]; head[x]=cnt; } int m,n,st; inline void dij(){ for(register int i=1;i<=n;i++) dis[i]=2147483647; dis[st]=0; for(register int i=1;i<=n;i++){ if(i!=st){ pus(i,2147483647); } } pus(st,0); for(register int i=1;i<=n;i++){ long long mn,mnid; do{ mnid=hp[1].id; mn=hp[1].w ; del(); }while(vis[mnid]); vis[mnid]=1; for(register int j=head[mnid];j!=-1;j=e[j].next){ dis[e[j].to]=min(dis[e[j].to],mn+e[j].w); pus(e[j].to ,dis[e[j].to]); } } } int main(){ memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&st); // cin>>n>>m>>st; int x,y,w; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&w); // cin>>x>>y>>w; add(x,y,w); } dij(); for(int i=1;i<=n;i++){ printf("%lld ",dis[i]); // cout<<dis[i]<<" "; } }
以下写法很标准,但是很慢
dijkstra STL版
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #define MAXN 30000 #define INF 2147483647 using namespace std; struct Node{ int id,v; bool operator < (const Node &aa) const { return this->v > aa.v; } }r,l; struct Edge{ int to,next,w; }; vector<Edge> e; int head[MAXN]; inline void add(int x,int y,int w){ Edge rr; rr.next =head[x]; rr.to = y; rr.w = w; head[x]=e.size(); e.push_back(rr); } int m,n,st; long long dis[MAXN]; bool vis[MAXN]; inline void dij(int st){ priority_queue<Node> Q; for(register int i=1;i<=n;i++) dis[i]=INF; dis[st]=0; for(register int i=1;i<=n;i++) if(i!=st) r.id = i,r.v = INF,Q.push(r); r.id = st; r.v = 0; Q.push(r); for(register int i=1;i<=n;i++){ do{ r=Q.top() ; Q.pop() ; }while(vis[r.id ]); vis[r.id ]=1; long long mn=r.v,mnid=r.id ; for(int j=head[mnid];j!=-1;j=e[j].next){ dis[e[j].to]=min(dis[e[j].to],mn+e[j].w); l.id = e[j].to ; l.v = dis[e[j].to]; Q.push(l); } } } int main(){ scanf("%d%d%d",&n,&m,&st); // cin>>n>>m>>st; memset(head,-1,sizeof(head)); int x,y,w; for(register int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&w); // cin>>x>>y>>w; add(x,y,w); } dij(st); for(register int i=1;i<=n;i++){ printf("%lld ",dis[i]); // cout<<dis[i]<<" "; } return 0; }