【差分约束】Is the Information Reliable?
Time Limit:1000MS Memory Limit:65536K
Total Submit:21 Accepted:12
Description
(reliable.pas/c/cpp)
【问题描述】
一次战争中,有N个防御站在一条直线上。
你得到一则信息,现在要判断这则信息是否可信。
信息包含M条提示,每条提示要么是精确的,要么是含糊的。
精确提示的格式是P A B X,表示防御站A在防御站B北面X光年处。
含糊提示的格式是V A B,表示防御站A在防御站B北面至少1光年处,但具体距离不知道。
Input
输入有多种数据。每组数据以两个整数N (0 < N ≤ 1000)和M (1 ≤ M ≤ 100000)开始。接下来M行,输入M条提示。
Output
每组数据输出一行。如果能布置这N个防御站的位置来满足这M条提示,则输出“Reliable”,否则输出“Unreliable”。
Sample Input
3 4
P 1 2 1
P 2 3 1
V 1 3
P 1 3 1
5 5
V 1 2
V 2 3
V 3 4
V 4 5
V 3 5
Sample Output
Unreliable
Reliable
Hint
本题数据不完整,请在本系统测试通过后到 http://poj.org/problem?id=2983 提交完整测试!
Source
POJ Monthly--2006.08.27, Dagger
把 a=b 号转换为 a>=b and a<=b
注意数组大小。
BellmanFord方法来解。
type
road=record
x,y,d:longint;
end;
var
n,m,mm,tot,pan:longint;
map:array[1..200000+10]of road;
d:array[0..1000+10]of longint;
procedure insert(x,y,d:longint);
begin
inc(tot);
map[tot].x:=x;
map[tot].y:=y;
map[tot].d:=d;
end;
procedure init;
var
i,a,b,s:longint;
c:char;
begin
tot:=0;
fillchar(map,sizeof(map),0);
readln(n,m);
mm:=m;
for i:=1 to m do
begin
read(c);
if c='P' then
begin
inc(mm);
readln(a,b,s);
insert(a,b,s);
insert(b,a,-s);
end;
if c='V' then
begin
readln(a,b);
insert(b,a,-1);
end;
end;
end;
procedure main;
var
i,j:longint;
begin
for i:=1 to 1000+10 do d[i]:=maxlongint div 2;
d[1]:=0;
for i:=1 to n-1 do
begin
pan:=0;
for j:=1 to mm do
if d[map[j].y]>d[map[j].x]+map[j].d then
begin
d[map[j].y]:=d[map[j].x]+map[j].d;
pan:=1;
end;
if pan=0 then
begin
writeln('Reliable');
exit;
end;
end;
writeln('Unreliable');
end;
begin
repeat
init;
main;
until seekeof;
end.
SFPA算法硬是没写出来。。
附上个WA的程序,求大神。
const
maxn=1000*2000;
type
road=record
x,y,d,next:longint;
end;
var
n,m,tot,pan,mm:longint;
map:array[1..200000+10]of road;
first:array[0..2000+10]of longint;
d,sum:array[0..2000+10]of longint;
mark:array[0..2000+10]of boolean;
f:array[1..maxn]of longint;
procedure insert(x,y,d:longint);
begin
inc(tot);
map[tot].x:=x;
map[tot].y:=y;
map[tot].d:=d;
map[tot].next:=first[x];
first[x]:=tot;
end;
procedure init;
var
i,a,b,s:longint;
c:char;
begin
tot:=0;
fillchar(map,sizeof(map),0);
fillchar(first,sizeof(first),0);
pan:=0;
readln(n,m);
mm:=m;
for i:=1 to m do
begin
read(c);
if c='P' then
begin
inc(mm);
readln(a,b,s);
if (a=b)and(s<>0) then begin pan:=1; writeln('Unreliable'); exit;end;
insert(a,b,s);
insert(b,a,-s);
end;
if c='V' then
begin
readln(a,b);
if (a=b) then begin pan:=1; writeln('Unreliable'); exit;end;
insert(b,a,-1);
end;
end;
for i:=1 to n do insert(0,i,0);
end;
procedure main;
var
i,x,y,t,head,tail:longint;
begin
for i:=1 to 2000+10 do d[i]:=maxlongint div 2;
fillchar(f,sizeof(f),0);
fillchar(sum,sizeof(sum),0);
fillchar(mark,sizeof(mark),0);
head:=1;
tail:=1;
mark[0]:=true;
f[1]:=0;
d[0]:=0;
while head<=tail do
begin
x:=f[(head) mod maxn];
t:=first[x];
while t>0 do
begin
y:=map[t].y;
if d[x]+map[t].d<d[y] then
begin
d[y]:=d[x]+map[t].d;
if not mark[y] then
begin
inc(sum[y]);
if sum[y]>n then
begin
writeln('Unreliable');
exit;
end;
inc(tail);
f[(tail)mod maxn]:=y;
mark[y]:=true;
end;
end;
t:=map[t].next;
end;
inc(head);
mark[x]:=false;
end;
for i:=1 to m do
if d[map[i].x]+map[i].d<d[map[i].y] then
begin
writeln('Unreliable');
exit;
end;
writeln('Reliable');
end;
begin
repeat
init;
if pan=0 then main;
until seekeof;
end.