差分约束求最优解 poj1201

以前用差分约束以为只能求可行解,没想到跟上下界网络流一样能求最优解。

题意:在[1,50000]中选取一系列整点是满足一系列不等式,在[a,b]中至少有c个整点,要求选取的整点数最少。

先说最优解问题:

1、最小解:

将初值赋为最小,利用松弛条件:d[u]+w[u,v]>=d[v]修改(使满足条件的值是最小的),于是连边条件为d[v]-d[u]>=w[u,v]。

2、最大解:

将初值赋为最大,利用松弛条件:d[u]+w[u,v]<=d[v]修改(使满足条件的值是最大的),于是连边条件为d[v]-d[u]<=w[u,v]。

针对此题目有几个不等式需分析出来:

1、S[b]-S[a-1]>=c(题目条件)

2、1>=S[I]-S[I-1]>=0(保证是整点且递增)

由2推出 a、S[I-1]-S[I]>=-1(由上式变形为求最小解的不等式)

               b、S[I]-S[I-1]>=0

建图,spfa即可过之。一开始不必建超级源点,只需将所有点入队。

const maxn=50000;maxm=1100000;
var d,tail:array[0..maxn]of longint;
    v:array[0..maxn]of boolean;
    st,next,sora,cost:array[0..maxm]of longint;
    n,ss:longint;
procedure link(x,y,z:longint);
begin
 inc(ss);next[tail[x]]:=ss;tail[x]:=ss;sora[ss]:=y;cost[ss]:=z
end;
procedure spfa;
var i,ne,na,h,r:longint;
begin
 fillchar(st,sizeof(st),0);
 h:=0;r:=1;st[1]:=maxn;
 for i:=0 to maxn-1 do begin
  inc(r);st[r]:=i;
  link(i+1,i,-1);link(i,i+1,0)
 end;
 fillchar(d,sizeof(d),0);fillchar(v,sizeof(v),false);
 repeat
  inc(h);ne:=st[h];
  i:=ne;
  while next[i]<>0 do begin
   i:=next[i];na:=sora[i];
   if d[ne]+cost[i]>d[na] then begin
    d[na]:=d[ne]+cost[i];
    if v[na] then begin
     v[na]:=false;
     inc(r);st[r]:=na
    end
   end
  end;
  v[ne]:=true
 until h>=r
end;
procedure origin;
var i:longint;
begin
 fillchar(tail,sizeof(tail),0);
 for i:=0 to maxn do tail[i]:=i;ss:=maxn
end;
procedure init;
var i,x,y,z:longint;
begin
 readln(n);
 origin;
 for i:=1 to n do begin
  readln(x,y,z);
  link(x-1,y,z)
 end;
 spfa;
 writeln(d[maxn])
end;
begin
assign(input,'1201.in');reset(input);
 init;
close(input)
end.


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值