WikiOI 1242 布局 (差分约束基础)

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号奶牛间可能的最大距离。

输入描述 Input Description
Line 1: Three space-separated integers: N, ML, and MD.

Lines 2..ML+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at most D (1 <= D <= 1,000,000) apart.

Lines ML+2..ML+MD+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at least D (1 <= D <= 1,000,000) apart.
输出描述 Output Description
Line 1: A single integer. If no line-up is possible, output -1. If cows 1 and N can be arbitrarily far apart, output -2. Otherwise output the greatest possible distance between cows 1 and N.
样例输入 Sample Input
4 2 1
1 3 10
2 4 20
2 3 3

样例输出 Sample Output
27

坑了个爹的差分约束系统!!!

这里补一下差分约束的基本规律(只能说是基本吧,只对大部分情况有用,而且也不能完全解决各类问题);

如果求类似于(满足条件的最小值)(至少需要多少XX才能排出要求的序列)的问题,那么可以确定是跑最长路(别问我为啥!)

如果求类似于(最大值)(最多可以。。)的问题,可以确定是跑最短路。

如果求最短路,可以列出各类不等式

d[a]>=d[b]+c
d[a]<=d[b]+c

分别化成如下形式

d[b]-d[a]<=-c
d[a]-d[b]<=c

则可以分别建立a到b,权值为-c的边

和b到a,权值为c的边。

(从减号右边向左边建边,权值为不等号右边的部分,求最长路的时候也可以类比转化不等式);

program mys;
type ab=^node;
node=record
data,ends:longint;
next:ab;
end;

var i,j,k,m,n,x,y,z,m1,m2,o:longint;
p:array[0..100010]of ab;
d:array[-10..100010]of longint;
b:array[0..100010]of boolean;
team:array[0..3000000]of longint;

procedure com(x,y,z:longint);
var i:ab;
begin 
i:=p[x];
new(p[x]);
p[x]^.ends:=y;
p[x]^.data:=z;
p[x]^.next:=i;
end;

procedure spfa;
var i:ab;
u,y,t,h:longint;
begin 
fillchar(d,sizeof(d),$5f);
fillchar(b,sizeof(b),false);
h:=0; t:=1; team[1]:=1; b[1]:=true; d[1]:=0;
while h<t do 
begin 
inc(h);
y:=team[h];
b[y]:=false;
i:=p[y];
while i<>nil do 
begin 
u:=i^.ends;
if d[u]>d[y]+i^.data then 
begin 
d[u]:=d[y]+i^.data;
if not b[u] then 
begin 
b[u]:=true;
inc(t);
if t=1000000 then 
begin 
writeln(-1);
halt;
end;
team[t]:=u;
end;
end;
i:=i^.next;
end;
end;
end;

begin 
readln(n,m1,m2);
for i:=1 to m1 do 
begin 
readln(x,y,z);
com(x,y,z);
end;
for i:=1 to m2 do 
begin 
readln(x,y,z);
com(y,x,-z);
end;
o:=0;
spfa;
if d[n]=d[-1] then 
writeln(-2) 
else
writeln(d[n]);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值