差分約束系統:如果乙個系統由n個變數和m個約束條件組成,其中每個約束條件形如 xj - xi<= bk ( i , j ∈ [1,n],k ∈ [1,m]),則稱其為差分約束系統。
例如如下的約束條件:
x1 - x2 <= 0 x1 - x5 <= -1
x2 - x5 <= 1 x3 - x1 <= 5
x4 - x1 <= 4 x4 - x3 <= -1
x5 - x3 <= -3 x5 - x4 <= -3
全都是兩個未知數的差小於等於某個常數(大於等於也可以,因為左右乘以-1就可以化成小於等於)。這樣的不等式組就稱作差分約束系統。
差分約束系統求解過程:
1.新建乙個圖,n個變數看作n個頂點,m個約束條件作為m條邊。每個頂點vi分別對於乙個未知量,每個有向邊對應兩個未知量的不等式。
2.為了保證圖的連通性,在圖中新加乙個節點vs,圖中每個節點vi都能從vs可達,建立邊w(vs,vi) = 0。
3.對於每個差分約束xj - xi <= bk(這裡是小於等於號),則建立邊w(xi,xj) = bk。
4.初始化dist = inf,dist[vs] = 0.
5.求解以vs為源點的單源最短路徑,推薦用spfa,因為一般可能存在負值。
如果圖中存在負權迴路,則該差分約束系統不存在可行解。
vs到某點如果不存在最短路徑,即最短路為inf,則對於該點表示的變數可以取任意值,都能滿足差分約束的要求,如果存在最短路徑,則得到該變數的最大值。
上述過程最終得到的解為滿足差分約束系統各項的最大值。
注意點:
1. 如果要求最大值想辦法把每個不等式變為標準 x - y <= k 的形式,然後建立一條從 y 到 x 權值為 k 的邊,變得時候注意 x - y < k => x - y <= k-1。
2. 如果要求最小值的話,變為 x - y >= k 的標準形式,然後建立一條從 y到 x 權值為 k 的邊,求出最長路徑即可。
3. 如果權值為正,用dijkstra,spfa,bellmanford都可以,如果為負不能用dijkstra,並且需要判斷是否有負環,有的話就不存在。
#include
#include
#include
#include
#include
#define inf 0x7fffffff
using
namespace
std;
const
int maxn = 1100;
const
int maxm = 30030;
struct edgenode
edges[maxm];
int head[maxn],dist[maxn],vis[maxn],outque[maxn],id;
void addedges(int u,int v,int w)
void spfa(int s,int n)
for(int i = head[u]; i != -1; i = edges[i].next)}}
}if(ans == -1) //出現負權迴路,不存在可行解
printf("-1\n");
else
if(dist[n] == inf) //可取任意值,都滿足差分約束系統
printf("-2\n");
else
printf("%d\n",dist[n]); //求使得源點 s 到 終點 t 的最大的值
}int main()
for(int i = 0; i < md; ++i)
//這裡不加也可以
// for(int i = 1; i < n; ++i)
// addedges(i+1,i,0);
spfa(1,n); //求使得源點 s 到 終點 t 的最大的值
}return
0;}
差分約束系統模板
差分約束系統 如果乙個系統由n個變數和m個約束條件組成,其中每個約束條件形如 xj xi bk i j 1,n k 1,m 則稱其為差分約束系統。例如如下的約束條件 x1 x2 0 x1 x5 1 x2 x5 1 x3 x1 5 x4 x1 4 x4 x3 1 x5 x3 3 x5 x4 3 上述過...
差分約束系統 模板
先來理解一下 有乙個已經求好的dis最短路陣列,有一條邊x y權值為w,那麼一定存在dis y dis x w,即dis y dis x w 那麼什麼是差分約束系統呢,就是給我一些不等式,我可以用最短路的思想把他們轉化成圖 即差分約束系統 然後加乙個超級原點0,0到其他所有點的地方初始化為0以後,去...
差分約束 模板
如果需要求的是兩個變數差的最大值,那麼需要將所有不等式轉變成 leq 的形式,建圖後求最短路 如果需要求的是兩個變數差的最小值,那麼需要將所有不等式轉化成 geq 的形式,建圖後求最長路。這是兩個最基本的規則 算是吧 差分約束的精髓就在於建圖,而這玩意兒個人感覺沒什麼好辦法,只能靠不停做題去找到那種...