好像没什么好说的
就是进队出队进队出队
然后我这个是没有加过判环的。。
反正判环很好写的对伐
All Right
Code:
procedure SPFA;
begin
front:=1; finish:=2;
queue[2]:=0; d[0]:=0;
while front<>finish do
begin
inc(front);
x:=queue[front];
i:=headlist[x];
while i<>-1 do
begin
if d[t[i]]>d[x]+weight[i] then begin
d[t[i]]:=d[x]+weight[i];
if not(vis[t[i]]) then begin
inc(finish);
queue[finish]:=t[i];
vis[t[i]]:=true;
end;
end;
i:=next[i];
end;
vis[x]:=false;
end;
end;
=====================================这里是萌萌哒的分割线===============================================
Updated on 10.4.2014
嗯这样我把判负环的发上来
就是如果进队超过n次 (突然无厘头地Orz进队爷)
那么就有负环
为什么呢?
我们知道,对于一个点进队了两次,那么这两次的路径经过的点数肯定会不一样
因为SPFA有点类似于BFS,如果两次经过的点数一样,那么在第二次的时候会检测到它已经在队列里了,所以就不会进队了嘛。。
所以它进队了n次,那么最后一次路径上肯定n+1个点
然后就有负权回路了。。
Code:
const shuru='test.in';
shuchu='test.out';
INF=1 shl 25;
var time,d,headlist:array[0..1001] of int64;
t,next,w:array[0..100001] of int64;
queue:array[0..1000001] of int64;
inq:array[0..1001] of boolean;
x,a,b,c,num,s,front,finish,i,j,k,n,m:longint;
procedure init;
begin
readln(n,m,s);
for i:=1 to n do headlist[i]:=-1;
d[s]:=0;
for i:=1 to m do
begin
readln(a,b,c);
inc(num);
next[num]:=headlist[a];
headlist[a]:=num;
t[num]:=b;
w[num]:=c;
end;
end;
procedure SPFA(s:longint);
begin
queue[1]:=s;
time[s]:=1; inq[s]:=true;
front:=0;
finish:=1;
for i:=1 to n do d[i]:=INF;
d[s]:=0;
fillchar(inq,sizeof(inq),false);
fillchar(time,sizeof(time),0);
time[s]:=1;
inq[s]:=true;
while finish<>front do
begin
inc(front);
if front>1000001 then front:=front-1000001;
x:=queue[front];
i:=headlist[x];
while i<>-1 do
begin
if d[t[i]]>d[x]+w[i] then begin
d[t[i]]:=d[x]+w[i];
if not(inq[t[i]]) then begin
inc(time[t[i]]);
if time[t[i]]>n then begin
writeln(-1);
halt;
end;
inq[t[i]]:=true;
inc(finish);
if finish>1000001 then finish:=finish-1000001;
queue[finish]:=t[i];
end
end;
i:=next[i];
end;
inq[x]:=false;
end;
end;
procedure main;
begin
init;
randomize;
SPFA(random(n)+1);
SPFA(s);
for i:=1 to n do
if d[i]<>INF then writeln(d[i])
else writeln('NoPath');
end;
begin
main;
end.