差分约束系统

21 篇文章 0 订阅
2 篇文章 0 订阅

嗯什么是差分约束系统

就是已知一组条件

  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。

格式

输入格式

第一行一个整数n(n<=50000),表示区间个数。

接下来n行,每行三个整数a,b,c(0<=a<=b<=50000,1<=c<=b-a+1),用一个空格隔开,意义如题目描述。

输出格式

一个数,即为答案

样例

样例输入

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

样例输出

6

限制

每个测试点1s

提示

由于官方数据不全,所以有几个点是自己做的
样例说明:
满足条件的最少元素序列:3,4,5,8,9,10
[3,7]中有3,4,5三个数
[8,10]中有8,9,10三个数
……

用一个前缀和s[i]表示从1..i中有几个选进来

然后就是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.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值