本题是一道典型的差分约束系统问题。关于差分约束系统,请visit 百度百科:http://baike.baidu.com/view/1008149.htm
简略成一句话,那就是:对于i-j<=k 这样一个条件,就在j和i之间连一条有向边,边权为k
对于本题,有两种条件,两头牛的距离不大于或者不小于k,距离不大于k的时候按照差分约束系统的条件即可进行,而距离不小于k时则可以按照如下数学方法转换:
原条件为:i-j>=k 可转化为 j-i<=-k,即在i与j之间连一条边权为-k的有向边。
之后一般的SPFA即可。如果存在负环,就说明不存在解,如果起点到终点没有路径,那么说明距离可以到达无穷大
SPFA判断负环的方法:如果一个共n个点的图中,有一点入队次数大于n-1,说明图中存在负环。
CODE
Program Layout;//By_thispoet Const maxn=1000; Var i,j,k,ml,md,s,n,a,b,p,sum :Longint; pre,other,last,len,times :Array[1..maxn*500]of Longint; h,t :Longint; seq :Array[1..maxn*500]of Longint; dist :Array[1..maxn]of Longint; Procedure Swap(var i,j:Longint); begin i:=i xor j; j:=i xor j; i:=i xor j; end; BEGIN readln(n,ml,md); for i:=1 to ml do begin readln(a,b,p); if a>b then Swap(a,b); inc(sum);pre[sum]:=last[a];last[a]:=sum;other[sum]:=b;len[sum]:=p; end; for i:=1 to md do begin readln(a,b,p); if a<b then Swap(a,b); inc(sum);pre[sum]:=last[a];last[a]:=sum;other[sum]:=b;len[sum]:=-p; end; {------------------init---------------------} h:=0;t:=1;seq[1]:=1; fillchar(dist,sizeof(dist),127); fillchar(times,sizeof(times),0); dist[1]:=0; while h<t do begin inc(h); i:=seq[h]; j:=last[i]; while j<>0 do begin k:=other[j]; if dist[k]>dist[i]+len[j] then begin dist[k]:=dist[i]+len[j]; inc(t);seq[t]:=k; inc(times[k]); if times[k]>n then begin writeln(-1); halt; end; end; j:=pre[j]; end; end; {-------------------SPFA--------------------} if dist[n]>(maxlongint>>1) then writeln(-2) else writeln(dist[n]); {----------------output it-------------------} END.