zoj2770 差分約束問題

來源:互聯網
上載者:User

標籤:差分約束系統

總的開說差分約束問題就是給出一系列不等式然後求問某一式子的最大值或者最小值。

差分約束問題詳解:

    比如有這樣一組不等式: 
   
X1 - X2 <= 0 
X1 - X5 <= -1 
X2 - X5 <= 1 
X3 - X1 <= 5                   不等式組(1) 
X4 - X1 <= 4 
X4 - X3 <= -1 
X5 - X3 <= -3 
X5 - X4 <= -3 

    全都是兩個未知數的差小於等於某個常數(大於等於也可以,因為左右乘以-1就可以化成小於等於)。這樣的不等式組就稱作差分約束系統。 
    這個不等式組要麼無解,要麼就有無數組解。因為如果有一組解{X1, X2, ..., Xn}的話,那麼對於任何一個常數k,{X1 + k, X2 + k, ..., Xn + k}肯定也是一組解,因為任何兩個數同時加一個數之後,它們的差是不變的,那麼這個差分約束系統中的所有不等式都不會被破壞。 
    
    差分約束系統的解法利用到了單源最短路徑問題中的三角形不等式。即對於任何一條邊u -> v,都有: 

d(v) <= d(u) + w(u, v) 

    其中d(u)和d(v)是從源點分別到點u和點v的最短路徑的權值,w(u, v)是邊u -> v的權值。 
    顯然以上不等式就是d(v) - d(u) <= w(u, v)。這個形式正好和差分約束系統中的不等式形式相同。於是我們就可以把一個差分約束系統轉化成一張圖,每個未知數Xi對應圖中的一個頂點Vi,把所有不等式都化成圖中的一條邊。對於不等式Xi - Xj <= c,把它化成三角形不等式:Xi <= Xj + c,就可以化成邊Vj -> Vi,權值為c。

在建立圖的時候應該與目標函數的符號相同,即目標函數為>=,不等式的符號也應該變為>=,再根據不等式建立圖;

相反,如果是<=,不等式也應該全部變為<=,再建立圖;

(一致性)符號是>=或者<=,並非<和>


上文就講了如何根據不等式建立圖,哪到底和問題的不等式的最大值或者最小值有什麼關聯呢?

如題目要求d(v) - d(u)的最小值,可以轉換成d(v) - d(u) >=M,而根據上文得知M為u->v的權值。

要想上式子成立,則應有min(d(v) - d(u))>=max(M),即轉成了求u->v最長的路徑即式子的最小值

相同,如果求d(v) - d(u)的最大值,這應該求u->v的最小路徑

對於差分不等式,a - b <= c ,求的是最短路,得到的是最大值;

對於差分不等式 a - b >= c ,求的是最長路,得到的是最小值。


關於補不補充源點:

當d(v) 和d(u)都已在圖中存在,則不需要補充源點。

當圖沒有目標源點的時候或者需要串連整個圖的時候,則需要補充源點。並補充關係。


如果圖中存在負權值迴路,則求出來的最短路徑沒有意義。也就是說不等式無解。所以要從是否有負權值迴路進而判斷有無解。


zoj求最小值:(差分不等式a-b>=c,求最長路,得到最小值)

#include <map>#include <set>#include <queue>#include <stack>#include <math.h>#include <vector>#include <cstdio>#include <string>#include<string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;int dist[1010];int n,m,a,b,c;struct edge{int to,cost;}cur;vector<edge>vec[1010];inline void read(int &m)//int{int x=0,f=1;char ch=getchar();//intwhile(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}m=x*f;}bool spfa()  //(差分不等式a-b>=c,求最長路,得到最小值){int cnt[1010];bool vis[1010];for(int i=1;i<=n;i++)dist[i]=-1111111111;memset(cnt,0,sizeof(cnt));memset(vis,0,sizeof(vis));vis[0]=1;dist[0]=0;queue<int>que;que.push(0);while(!que.empty()){int v=que.front();que.pop();if(++cnt[v]>=n)return 0;vis[v]=0;for(int i=0;i<vec[v].size();i++){edge temp=vec[v][i];if(dist[temp.to]<dist[v]+temp.cost){dist[temp.to]=dist[v]+temp.cost;if(!vis[temp.to]){vis[temp.to]=1;que.push(temp.to);}}}}return 1;}int main(){while(~scanf("%d %d",&n,&m)){for(int i=0;i<=n;i++)vec[i].clear();for(int i=1;i<=n;i++){read(a);cur.to=i;cur.cost=0;vec[i-1].push_back(cur);  //Ai>=0  S(i-1)-Si<=0     cur.to=i-1;cur.cost=-a;vec[i].push_back(cur); //Ai<=a   Si-S(i-1)<=0cur.to=i;cur.cost=0;vec[0].push_back(cur);  //Si-S0>=0     //0點為新添上去的源點,與其他節點建立關係}for(int i=1;i<=m;i++){read(a),read(b),read(c);cur.to=b;cur.cost=c;vec[a-1].push_back(cur);  //Sb-Sa-1>=c}if(spfa())printf("%d\n",dist[n]);else printf("Bad Estimations\n");}return 0;}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.