SPFA

来源:互联网 发布:大话数据库 pdf 下载 编辑:程序博客网 时间:2024/06/03 21:05

SPFA是类似bfs的一种图论方法,运用队列更新dis[i],求得图中1~n的最短路径。

SPFA中用到dis[i]表示图中每一点距离起点的长度,bz[i]用来记录编号为i的点是否入队,a[x,y]表示图中x~y之间的距离,b[x,i]表示编号为x的点的第i条边的终点,每次更新这个终点到起点的距离,以当前入队的点来更新,最后求出答案。
ps:这种方法有空间限制,因为有二维数组。
代码:

var        dis,f:array[0..100000]of longint;        a,b:array[0..1000,0..1000]of longint;        bz:array[1..1000]of boolean;        i,j,head,tail,k,n,m,x,y,z,t:longint;begin        readln(n,m);        for i:=1 to m do        begin                readln(x,y,z);                inc(b[x,0]);//记录编号为x的点有多少条边                b[x,b[x,0]]:=y;                if (a[x,y]>z)or(a[x,y]=0) then a[x,y]:=z;        end;        head:=0;        tail:=1;        for i:=1 to n do                if dis[i]=0 then dis[i]:=maxlongint;        dis[1]:=0;        bz[1]:=true;        f[1]:=1;        repeat                inc(head);                k:=f[head];                for i:=1 to b[k,0] do                begin                        if a[k,b[k,i]]+dis[k]<dis[b[k,i]] then//更新                        begin                                dis[b[k,i]]:=a[k,b[k,i]]+dis[k];                                if bz[b[k,i]]=false then//判断是否入过队                                begin                                        inc(tail);                                        f[tail]:=b[k,i];                                        bz[b[k,i]]:=true;                                end;                        end;                end;                bz[k]:=false;        until head>=tail;        for i:=2 to n do        begin                if dis[i]=maxlongint then writeln(-1)                else writeln(dis[i]);        end;end.

既然这种方法不行那么我们有就可以用数组模拟这个过程,

tov[i]表示编号为i的边的终点;
next[i]表示编号为i的边下一个要搜索的边;
last[i]表示以i为节点开始的最后一条边;
len[i]表示编号为i的权值;

那么程序改成这样:

var        f,dis,next,last,len,tov:array[1..100000]of longint;        bz:array[1..100000]of boolean;        head,tail,n,m,i,x,y,z,tot,daan:longint;procedure insert(x,y,z:longint);//插入过程begin        inc(tot);        tov[tot]:=y;        len[tot]:=z;        next[tot]:=last[x];        last[x]:=tot;end;procedure spfa;var        x,y,i:longint;begin        f[1]:=1;        bz[1]:=true;        head:=0;        tail:=1;        for i:=1 to n do dis[i]:=maxlongint div 2;        dis[1]:=0;        while  head<>tail do        begin                head:=head mod n+1;                x:=f[head];                i:=last[x];                while (i<>0) do                begin                        y:=tov[i];                        if (dis[y]>dis[x]+len[i])then                        begin                                dis[y]:=dis[x]+len[i];                                if (not bz[y])then                                begin                                        tail:=tail mod n+1;                                        f[tail]:=y;                                        bz[y]:=true;                                end;                        end;                        i:=next[i];                end;                bz[x]:=false;        end;end;begin        read(n,m);        for i:=1 to m do        begin                readln(x,y,z);                insert(x,y,z);//有向边        end;        spfa;        for i:=2 to n do        begin                if(dis[i]=maxlongint div 2)then                begin                        writeln('-1');                end                else                begin                        writeln(dis[i]);                end;        end;end.
1 0
原创粉丝点击