【差分约束】Is the Information R…

【差分约束】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.

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值