序列长度【差分约束】
【问题描述】
有一个整数序列,我们不知道她的长度是多少(即序列中整数的个数),但我们知道在某些区间中至少有多少个整数,用区间 [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更短的合法序列了.
注意:序列中不能有相同数字
用差分约束做!
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.
posted on 2011-10-31 19:26 ushiojamie 阅读(259) 评论(0) 编辑 收藏 举报