【差分约束系统】序列长度

  序列长度

【问题描述】

  有一个整数序列,我们不知道她的长度是多少(即序列中整数的个数),但我们知道在某些区间中至少有多少个整数,用区间 [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更短的合法序列了.

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

=================================

====================================

type
  pnode=^node;
  node=record
         x,v:longint;
         next:pnode;
       end;
  tnode=record
         a,b,c:longint;
       end;
var
  n:longint;
  ti:array[-1..1000]of tnode;
  map:array[-1..1000]of pnode;
  queue:array[1..200000]of longint;
  dist:array[-1..1000]of longint;
  times:array[-1..1000]of longint;
  v:array[-1..1000]of boolean;
procedure init;
begin
  assign(input,'sequence.in');
  assign(output,'sequence.out');
  reset(input); rewrite(output);
end;

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

procedure ins(a,b,c:longint);
var
  p:pnode;
begin
  new(p);
  p^.x:=b;
  p^.v:=c;
  p^.next:=map[a];
  map[a]:=p;
end;

procedure spfa;
var
  l,r:longint;
  x:longint;
  p:pnode;
begin
  fillchar(v,sizeof(v),true);
  fillchar(dist,sizeof(dist),$7);
  dist[-1]:=0;
  v[-1]:=false;
  l:=0; r:=1;
  queue[1]:=-1;
  repeat
    inc(l);
    x:=queue[l];
    p:=map[x];
    while p<>nil do
      begin
        if dist[x]+p^.v<dist[p^.x] then
         begin
           inc(times[p^.x]);
           if times[p^.x]=n+2 then
             begin
               writeln(-1);
               terminate;
             end;
           dist[p^.x]:=dist[x]+p^.v;
           if v[p^.x] then
             begin
               inc(r);
               queue[r]:=p^.x;
               v[p^.x]:=false;
             end;
         end;
        p:=p^.next;
      end;
    v[x]:=true;
  until l>=r;
end;

procedure main;
var
  i:longint;
  t:longint;
begin
  readln(n);
  for i:=1 to 1000 do map[i]:=nil;
  t:=0;
  for i:=1 to n do
    begin
      readln(ti[i].a,ti[i].b,ti[i].c);
      if ti[i].b>t then t:=ti[i].b;
      ins(ti[i].b,ti[i].a-1,-ti[i].c);
    end;
  for i:=1 to t do begin ins(i-1,i,1); ins(i,i-1,0); end;
  for i:=0 to t do begin ins(-1,i,0); end;
  fillchar(times,sizeof(times),0);
  spfa;
  writeln(dist[t]-dist[0]);
end;

begin
  init;
  main;
  terminate;
end.


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值