差分约束系统

差分约束系统

Tags: 图论,不等式


水题(bzoj 1731)

  • 裸差分约束,n头牛【1,n】,(ml条这样的信息)对于两头有好感的牛距离不超过w,(md条这样的信息)对于两头有反感的牛距离至少w,且多头牛可以共享一个点,求最后一头牛和第一头牛距离最大是多少

  • 按要求建图,使用bellman或者spfa

/*
4 2 1
1 3 10
2 4 20
2 3 3

Sample Output
27
四只牛分别在0,7,10,27.

*/
#include <bits/stdc++.h>
using namespace std; 
struct edge{
	int from,cost,to;
}e[100000];
int k=0; 
void build(int x,int y,int w){
	//e[k].from=x,e[k].to=y,e[k].cost=w;
	e[k]=edge{x,w,y};
	k++;
}
int d[1005];
int n;
const int inf=0x7f7f7f7f; 
bool bellman(int s){
	memset(d,0x7f,sizeof(d));
	d[s]=0;
	bool update=0;
	
	for(int i=1;i<=n;i++){
		update=0;
		
		for(int j=0;j<k;j++){
			edge& es=e[j];
			if(es.from!=inf&&d[es.from]+es.cost<d[es.to]){
				d[es.to]=d[es.from]+es.cost;
				update=1;
				if(i==n)return 0;
			}
		}
		if(!update)return 1;
	}
	return 1;
} 
int main(){
	int ml,md;
	scanf("%d %d %d",&n,&ml,&md);
	int x,y,w;
	while(ml--){
		scanf("%d %d %d",&x,&y,&w);//y-x<=w;建有向边x->y,
		build(x,y,w);   
	}
	while(md--){
		scanf("%d %d %d",&x,&y,&w);//y-x>=w;x-y<=(-w)
		build(y,x,-w);
	}
	for(int i=2;i<n;i++)build(i,i-1,0);//多头牛共享一个点,建0边
	
	if(!bellman(1)){
		printf("%d",-1);
	}
	else{
		if(d[n]==inf)printf("%d",-2);
		else {
			for(int i=1;i<=n;i++){
				printf("%d ",d[i]);//打印可行解,题目答案即为d[n];
			}                      //这里没有题目要求输出
		}
	}
	return 0;
}

最短路算法

  • 差分约束系统一般使用bellman和spfa求最短路,也可以用来求最长路径,只需将松弛操作从 &lt; &lt; <改成 &gt; &gt; >

差分约束系统

  • 条件:每个不等式只含两个变量,且系数为1和-1.

  • 不等式建边:a-b<=c(一定要小于等于),a<=b+c,to<=from+cost,建立b->a的有向边

  • 最大值最小值的理解:差分约束系统是将不等式合并成 不 等 式 约 束 下 求 首 位 距 离 最 大 值 a − b &lt; = c 1 a − b &lt; = c 2 a − b &lt; = c 3 . . . . . . m a x ( a − b ) = m i n ( c 1 , c 2 , . . . ) 相 当 于 最 短 路 径 不等式约束下求首位距离最大值\\a-b&lt;=c1\\a-b&lt;=c2\\a-b&lt;=c3\\......\\max(a-b)=min(c1,c2,...)\\相当于最短路径 ab<=c1ab<=c2ab<=c3......max(ab)=min(c1,c2,...)--------------------------------------------------------------------------- 不 等 式 约 束 下 求 首 位 距 离 最 小 值 a − b &gt; = c 1 a − b &gt; = c 2 a − b &gt; = c 3 . . . . . . m i n ( a − b ) = m a x ( c 1 , c 2 , . . . ) 相 当 于 最 长 路 径 不等式约束下求首位距离最小值\\a-b&gt;=c1\\a-b&gt;=c2\\a-b&gt;=c3\\......\\min(a-b)=max(c1,c2,...)\\相当于最长路径 ab>=c1ab>=c2ab>=c3......min(ab)=max(c1,c2,...),

  • 不等式标准化:(此处求两个点距离的最大值,如果求最小值则转化为 &gt; = &gt;= >=求最长路径)

a-b>=c  ->   b-a<=-c;
a-b<c   ->   a-b<=c-1;
a-b>c   ->   b-a<-c   ->   b-a<=-c-1;
a-b=c   ->   a-b<=c&&a-b>=c
  • 可行解:最大值(最小值):有负(正)环时距离可以无限小(大),不可达时(两个点之间没有约束关系)距离无限大(小),有解的情况下d[i]为每个点对应的位置(一组可行解)

差分约束详解及金典模型

  • 线性约束
  • 区间约束的(d[i]表示(0,i)区间)
  • 位置条件约束(二分+差分约束)

参考博客传送门感谢博主

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值