嗯什麼是差分約束系統
就是已知一組條件
x1-x2<=m1
xi-xj<=mp;
......
然後讓你求x1-xn的最大值
ans:
構圖
構造x1,x2......xn n個點
x1,x2之間連權爲m1的邊
xi,xj之間連權爲mp的邊
......
求x1到xn的最短路就可以了
如果有x1-x2>=m1或者x1-x2<m1什麼奇怪的條件就把它轉化一下就好了
//通常會和前綴和什麼的一起亂搞搞
Vijos 區間
描述
對於一個整數序列,給出的一個三元組[a,b,c]表示該序列在閉區間[a,b]的整數至少有c個,其中a,b,c均爲整數。
題目將給出n個三元組,求同時滿足這n個三元組的序列的最少元素個數是多少。如果不存在這樣的滿足要求的序列,則輸出-1。
然後就是a..b裏有c個數就是s[b]-s[a-1]>=c;
然後就構造差分約束系統
然後注意a可能會取到0
所以把整個數軸向左移(即讀入的時候把a,b+1)來做
Code://用的是沒加優化的SPFA 跑的飛起,加了優化反而TLE
const INF=1 shl 20;
var d,headlist:array[0..50001] of longint;
t,weight,next:array[0..5000001] of longint;
vis:array[0..50001] of boolean;
queue:array[0..10000001] of longint;
x,a,b,c,num,i,j,k,n,tot,front,finish:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a);
exit(b);
end;
procedure addedge(x,y,z:longint);
begin
inc(num);
next[num]:=headlist[x];
headlist[x]:=num;
t[num]:=y;
weight[num]:=z;
end;
procedure GotTu;
begin
for i:=0 to 50001 do headlist[i]:=-1;
for i:=0 to 50001 do d[i]:=INF;
fillchar(vis,sizeof(vis),false);
readln(n);
for i:=1 to n do
begin
readln(a,b,c);
if c>b-a+1 then begin
writeln(-1);
halt;
end;
tot:=max(tot,b+1);
addedge(a,b+1,-c);
end;
for i:=1 to tot do
begin
addedge(i,i-1,1);
addedge(i-1,i,0);
end;
end;
procedure SPFA;
begin
front:=1; finish:=2;
queue[2]:=0; d[0]:=0;
while front<>finish do
begin
inc(front);
x:=queue[front];
i:=headlist[x];
while i<>-1 do
begin
if d[t[i]]>d[x]+weight[i] then begin
d[t[i]]:=d[x]+weight[i];
if not(vis[t[i]]) then begin
inc(finish);
queue[finish]:=t[i];
vis[t[i]]:=true;
end;
end;
i:=next[i];
end;
vis[x]:=false;
end;
end;
procedure main;
begin
GotTu;
spfa;
writeln(-d[tot]);
end;
begin
main;
end.