您的位置:首页 > 其它

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

2016-11-12 19:31 225 查看
差分约束建图方法

第一:

感觉难点在于建图

第二:

①:对于差分不等式,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
=dis[0] then writeln(-2)

else writeln(dis
);

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: