序列长度【差分约束】

【问题描述】

  有一个整数序列,我们不知道她的长度是多少(即序列中整数的个数),但我们知道在某些区间中至少有多少个整数,用区间 [ai,bi,ci]来描述它,[ai,bi,ci]表示在该序列中处于[ai,bi]这个区间的整数至少有ci个。现在给出若干个这样的区间,请你求出满足条件的最短序列长度是多少。如果不存在则输出 -1。

【文件输入】

   第一行包括一个整数n(n<=1000),表示区间个数;

   以下n行每行描述这些区间,第i+1行三个整数ai,bi,ci,由空格隔开,其中0<=ai<=bi<=1000 而且 1<=ci<=bi-ai+1。

【文件输出】

    文件输出只有一个整数表示满足要求序列长度的最小值。

【样例输入】

 5
 3 7 3
 8 10 3
 6 8 1
 1 3 1
 10 11 1

【样例输出】

 6

 

提示:

其中两个合法序列分别为(3,5,7,8,9,10) (3,4,6,8,9,10),长度都为6,不可能有比6更短的合法序列了.

注意:序列中不能有相同数字

 

 

 

用差分约束做!

Bellman-Ford每次更新操作为 dist[u]+w[u,v]<dist[v] then 更新
所以最后有dist[v]<=dist[u]+w[u,v]
变形一下有dist[u]-dist[v]>=-w[u,v]
把ai bi ci 变形一下有 Sbi-S(ai-1)>=ci
所以可以建立联系
分为    1)Sbi-S(ai-1)>=Ci
         2)Si-S(i-1)>=0
         3)S(i-1)-Si>=-1
 
建立图以后 把所有边的值赋为相同的 能松弛的就松弛 最后输出的是abs(dist[max]-dist[0])(max是区间边界)
 

program sequence;
type
  node=^point;
  point=record
          tot,bian:longint;
          next:node;
        end;
var
  q:array[0..30001] of longint;
  dist:array[0..3001] of longint;
  v:array[0..3001] of boolean;
  a:array[0..3001] of node;
  n,max:longint;

procedure terminate;
begin
  close(input);close(output);
end;

procedure init;
var p:node;
    i,a1,a2,a3:longint;
begin
  assign(input,'sequence.in');reset(input);
  assign(output,'sequence.out');rewrite(output);
  readln(n);
  for i:=1 to 1001 do a[i]:=nil;


  for i:=1 to n do begin
    readln(a1,a2,a3);
    new(p);p^.bian:=a1-1;p^.tot:=-1*a3;p^.next:=a[a2];a[a2]:=p;
    if (a2>max) then max:=a2;
  end;


  for i:=0 to (max-1) do begin
    new(p);p^.bian:=i+1;p^.tot:=1;p^.next:=a[i];a[i]:=p;
    new(p);p^.bian:=i;p^.tot:=0;p^.next:=a[i+1];a[i+1]:=p;
  end;
end;

procedure main;
var head,tail,i:longint;
    p:node;
begin
  fillchar(dist,sizeof(dist),0);      
  fillchar(v,sizeof(v),0);
  head:=0;tail:=0;
  for i:=0 to max do begin
    inc(tail);
    q[tail]:=i;
  end;
  while (head<>tail) do begin
    inc(head);if (head=30001) then head:=1;
    v[q[head]]:=false;
    p:=a[q[head]];
    while (p<>nil) do begin
      if (dist[q[head]]+p^.tot<dist[p^.bian]) then begin
        dist[p^.bian]:=dist[q[head]]+p^.tot;
        if not(v[p^.bian]) then begin
          inc(tail);if (tail=30001) then tail:=1;
          q[tail]:=p^.bian;v[p^.bian]:=true;
        end;
      end;
      p:=p^.next;
    end;
  end;
  writeln(abs(dist[max]-dist[0]));            
end;

begin
  init;
  main;
  terminate;
end.

转载于:https://www.cnblogs.com/ushiojamie/archive/2011/10/31/2230645.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值