标签:
spfa,不用多讲了吧,相当实用的BF队列优化算法,裸代码如下
program spfa; var pre,last,other,long:array[0..1000001] of longint; d,short:array[0..1000001] of longint; ok:array[0..1000001] of boolean; head,tail,m,n,i,j,k,tot,x,y,z:longint; procedure add(x,y,z:longint); begin inc(tot); pre[tot]:=last[x]; last[x]:=tot; other[tot]:=y; long[tot]:=z; end; begin readln(n,m); for i:=1 to m do begin readln(x,y,z); add(x,y,z); add(y,x,z); end; fillchar(ok,sizeof(ok),true); fillchar(short,sizeof(short),127); head:=0; tail:=1; d[1]:=1; short[1]:=0; while head<tail do begin inc(head); ok[d[head]]:=true; i:=last[d[head]]; while i<>0 do begin if short[other[i]]>short[d[head]]+long[i] then begin short[other[i]]:=short[d[head]]+long[i]; if ok[other[i]] then begin ok[other[i]]:=false; inc(tail); d[tail]:=other[i]; end; end; i:=pre[i]; end; end; for i:=1 to n do writeln(short[i]); end.
用这个程序轻松求出从标号1到各点的距离。
如果起点不是1,又要怎么做呢?
1)暴力法
很容易想到,数组存下所有边的起点,中点及权值,再将所有点权加上(n-x) mod n + 1,其中n表示点数,x表示所求起点。
正确性显然,就不多证明了。
2)更改spfa主要部分如下:
①将队首元素更改为所求节点
②由该点向外拓展至各边并比较,记录
由此,我们将一个spfa变成了可以求从任意起点到其他点最短路的算法
代码就不贴了,大家可以自己写一下,利用上面的可以直接改变量,或者把主要部分放进procedure里
3)slf优化
详见百度百科,大家可以自行查找,通过将部分点放于队首减少更新的算法优化,代码贴c++了,DeAR神犇手打
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; //variable// int last[100000],prel[100000],dest[100000],cost[100000],tot=1; int vis[100000],q[1000000],dis[100000]; //function prototype// void addline(int,int,int); void spfa_slf(int); //solve// int main(){ int n,m,u,v,w; scanf("%d%d",&n,&m); for (int i=0;i<m;++i){ scanf("%d%d%d",&u,&v,&w); addline(u,v,w); } spfa_slf(1); printf("%d\n",dis[n]); system("pause"); return 0; } void addline(int u,int v,int w){ dest[++tot]=v; prel[tot]=last[u]; last[u]=tot; cost[tot]=w; } void spfa_slf(int x){ memset(dis,0x7f,sizeof dis); memset(vis,0,sizeof vis); int he=500000,ta=500000; dis[x]=0;vis[x]=1;q[he]=x; while (he<=ta){ int u=q[he++]; vis[u]=0; for (int k=last[u];k;k=prel[k]){ if (dis[dest[k]]>dis[u]+cost[k]){ dis[dest[k]]=dis[u]+cost[k]; if (!vis[dest[k]]){ vis[dest[k]]=1; if (dis[dest[k]]<dis[u]){ q[--he]=dest[k]; }else{ q[++ta]=dest[k]; } } } } } }
标签:
原文地址:http://www.cnblogs.com/victorslave/p/4796081.html