SPFA

21 篇文章 0 订阅
4 篇文章 0 订阅

好像没什么好说的

就是进队出队进队出队

然后我这个是没有加过判环的。。

反正判环很好写的对伐

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.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值