差分約束系統

差分約束系統

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的有向邊

  • 最大值最小值的理解:差分約束系統是將不等式合併成ab&lt;=c1ab&lt;=c2ab&lt;=c3......max(ab)=min(c1,c2,...)不等式約束下求首位距離最大值\\a-b&lt;=c1\\a-b&lt;=c2\\a-b&lt;=c3\\......\\max(a-b)=min(c1,c2,...)\\相當於最短路徑---------------------------------------------------------------------------ab&gt;=c1ab&gt;=c2ab&gt;=c3......min(ab)=max(c1,c2,...)不等式約束下求首位距離最小值\\a-b&gt;=c1\\a-b&gt;=c2\\a-b&gt;=c3\\......\\min(a-b)=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)區間)
  • 位置條件約束(二分+差分約束)

參考博客傳送門感謝博主

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章