题目大意:有n个点在一条直线上,有两类关系:P(x,y,v)表示x在y北边v距离处,V(x,y)表示x在y北边至少1距离出,给出一些这样的关系,判断是否有矛盾。
分析:
差分约束模板题,约束条件P:a-b>=v a-b<=v即a-b>=v b-a<=-v,V:a-b>=1即b-a<=-1,构图spfa判负权回路即可。
需要注意 的是存图时不能用一个二维数组存边权,因为两点间会有多条边。、
spfa判断负权回路的方法,记录每个点进队次数,超过点的数目即存在负权回路。
代码:
program infor; type point=^node; node=record x,len:longint; next:point; end; var a:array[0..1000]of point; q:array[0..500000]of longint; dis,vis:array[0..1000]of longint; g:array[0..1000]of boolean; n,i,m,x,y,v:longint; c:char; p:point; procedure put(x,y,v:longint); var p:point; begin new(p); p^.x:=x; p^.len:=v; p^.next:=a[y];a[y]:=p; end; procedure getnew; var i:longint; begin fillchar(q,sizeof(q),0); fillchar(g,sizeof(g),false); fillchar(vis,sizeof(vis),0); for i:=1 to n do dis[i]:=maxlongint div 3; for i:=0 to n do begin dispose(a[i]); new(a[i]); a[i]:=nil; end; dis[0]:=0; g[0]:=true; q[1]:=0; end; function spfa:boolean; var x,y,h,t:longint; p:point; begin h:=0; t:=1; while h<t do begin inc(h); x:=q[h]; g[x]:=false; new(p);p:=a[x]; while p<>nil do begin y:=p^.x; if dis[x]+p^.len<dis[y] then begin dis[y]:=dis[x]+p^.len; if g[y]=false then begin inc(t); q[t]:=y; g[y]:=true; end; inc(vis[y]); if vis[y]>n then exit(false); end; p:=p^.next; end; end; exit(true); end; begin readln(n,m); while (n<>0)or(m<>0) do begin getnew; for i:=1 to n do put(i,0,0); for i:=1 to m do begin read(c); if c=‘P‘ then begin read(x,y,v); put(x,y,v); put(y,x,-v); end else if c=‘V‘ then begin read(x,y); put(y,x,-1); end; if i<m then readln; end; if spfa then writeln(‘Reliable‘) else writeln(‘Unreliable‘); n:=0; m:=0; readln(n,m); end; end.
时间: 2024-10-14 12:49:01