wikioi 1242 布局(奶牛排队) 差分约束

来源:互联网 发布:证明贪心算法是最优解 编辑:程序博客网 时间:2024/04/28 21:30

差分约束建图方法
第一:
感觉难点在于建图
第二:
①:对于差分不等式,a - b <= c ,建一条 b 到 a 的权值为 c 的边,求的是最短路,得到的是最大值
②:对于不等式 a - b >= c ,建一条 b 到 a 的权值为 c 的边,求的是最长路,得到的是最小值
③:存在负环的话是无解
④:求不出最短路(dist[ ]没有得到更新)的话是任意解

或是

1.对于一个全部都是<=号的不等式组,我们可以将每个式子转化为Xi<=Xj+W(i,j),那么就建一条边,Xj->Xi=W(i,j),然后利用最短路径解决问题,在x0定死的情况下,求得最小值

2.对于一个全部都是>=号的不等式组,我们可以将每个式子转化为Xi>=Xj+W(i,j),那么就建一条边,Xj->Xi=W(i,j),然后利用最长路径解决问题,在x0定死的情况下,求得最大值

如果dis[Xi]为inf或-inf,那么Xi为任意解

来结合题目看下:

1242 布局 2005年USACO
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
查看运行结果
题目描述 Description
当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些。FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食。奶牛排在队伍中的顺序和它们的编号是相同的。因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上。即使说,如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标。

一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数L。另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数D。给出ML条关于两头奶牛间有好感的描述,再给出MD条关于两头奶牛间存有反感的描述。(1<=ML,MD<=10000,1<=L,D<=1000000)

你的工作是:如果不存在满足要求的方案,输出-1;如果1号奶牛和N号

奶牛间的距离可以任意大,输出-2;否则,计算出在满足所有要求的情况下,1号奶牛和N号奶牛间可能的最大距离。

思路:

1.首先让求最大距离,确定是跑最短路

2.则所有方程转化成a-b<=c的情况,建一条b->a的权值为c的边

结合本题来说:有好感的牛:为b-a<=c(b>a题目条件),则直接建a->b的边

互相反感的牛:b-a>=c,转换成a-b<=-c,建一条b->a的权值为-c的边

以下为代码:
program df;
type point=^node;
node=record
date,ends:longint;
next:point;
end;
var i,j,n,m,x,y,z,k,t:longint;
ff:boolean;
path:array[0..200000] of point;
b:array[0..200000] of boolean;
tm:array[0..5000000] of longint;
a,c,dis:array[0..200000] of longint;
procedure com(x,y,z:longint);
var i:point;
begin
i:=path[x];
new(path[x]);
path[x]^.ends:=y;
path[x]^.date:=z;
path[x]^.next:=i;
end;

procedure init;
var i,j:longint;
begin
for i:=0 to n do
begin
dis[i]:=maxlongint div 3;
b[i]:=false;
end;
end;

procedure spfa(x:longint);
var i:point;
h,t,u,y:longint;
begin
init;
h:=0; t:=1; dis[x]:=0; tm[1]:=x; b[x]:=true;
repeat
inc(h);
if h=3000000 then
begin
ff:=true;
exit;
end;
u:=tm[h];
b[u]:=false;
i:=path[u];
while i<>nil do
begin
y:=i^.ends;
if dis[y]>dis[u]+i^.date then
begin
dis[y]:=dis[u]+i^.date;
if not b[y] then
begin
inc(t);
tm[t]:=y;
b[y]:=true;
end;
end;
i:=i^.next;
end;
until h=t;
end;

begin
readln(n,m,k);
for i:=1 to m do
begin
readln(x,y,z);
com(x,y,z);
end;
for i:=1 to k do
begin
readln(x,y,z);
com(y,x,-z);
end;
//for i:=1 to n-1 do
//com(i+1,i,0); //本题情况特殊,加不加无所谓
ff:=false;
spfa(1);
if ff then
begin
writeln(-1);
halt;
end;
if dis[n]=dis[0] then writeln(-2)
else writeln(dis[n]);
end.

0 0