題意:給出n個整數區間[ai,bi],並且給出乙個約束ci,( 1<= ci <= bi-ai+1),使得陣列z在區間[ai,bj]的個數》= ci個,求出陣列z的最小長度。
思路:建立差分約束系統。因為這裡要求陣列長度的最小值,要變為x-y>=k的標準形式。
設陣列 s[j] 表示陣列 z 區間[0,j]裡包含的元素個數。所以 s[bi+1] - s[ai] >= ci,注意是 j+1,
隱含條件 0 <= s[i+1]-s[i] <= 1;
故差分約束系統為:
s[bi+1] - s[ai] >= ci;
s[i+1] - s[i] >= 0;
s[i] - s[i+1] >= -1;
然後鄰接表建圖求最長路。
1 #include2 #includeview code3 #include4 #include5
using
namespace
std;67
const
int maxn = 500100;8
const
int inf = 0x3f3f3f3f;9
struct
node
10edge[maxn];
1415
intn,p[maxn],cnt;
16int
min,max;
17int
dis[maxn],instack[maxn],vexcnt[maxn];
1819
void add(int u, int v, int
w)20
2829
bool
spfa()
3062}63
}64}65
return
true;66
}6768int
main()
6984
for(int i = min; i < max; i++)
8589
spfa();
90 printf("
%d\n
",dis[max]-dis[min]);
91return0;
92 }
關於差分約束:
比如給出三個不等式,b-a<=k1,c-b<=k2,c-a<=k3,求出c-a的最大值,我們可以把a,b,c轉換成三個點,k1,k2,k3是邊上的權,如圖
由題我們可以得知,這個有向圖中,由題b-a<=k1,c-b<=k2,得出c-a<=k1+k2,因此比較k1+k2和k3的大小,求出最小的就是c-a的最大值了
根據以上的解法,我們可能會猜到求解過程實際就是求從a到c的最短路徑,沒錯的....簡單的說就是從a到c沿著某條路徑後把所有權值和k求出就是c -a<=k的乙個
推廣的不等式約束,既然這樣,滿足題目的肯定是最小的k,也就是從a到c最短距離...
理解了這裡之後,想做題還是比較有困難的,因為題目需要變形一下,不能單純的算..
首先以poj3159為例,這個比較簡單,就是給出兩個點的最大差,然後讓你求1到n的最大差,直接建圖後用bellman或者spfa求最短路就可以過了
稍微難點的就是poj1364,因為他給出的不等式不是x-y<=k形式,有時候是大於號,這樣需要我們去變形一下,並且給出的還是》,《沒有等於,都要變形
再有就是poj1201,他要求出的是最長距離,那就要把形式變換成x-y>=k的標準形式
注意點:
1.如果要求最大值想辦法把每個不等式變為標準x-y<=k的形式,然後建立一條從y到x權值為k的邊,變得時候注意x-yx-y<=k-1
如果要求最小值的話,變為x-y>=k的標準形式,然後建立一條從y到x的k邊,求出最長路徑即可
2.如果權值為正,用dj,spfa,bellman都可以,如果為負不能用dj,並且需要判斷是否有負環,有的話就不存在
Intervals 差分約束系統
題意 給定n個整數閉區間 a,b 和n個整數c,求乙個最小的整數集合z,滿足z裡邊的數中範圍在閉區間 a,b 的個數不小於c個。思路 根據題目描述,可建模成乙個差分約束系統。設s i 表示小於等於i的整數的個數,r表示最大的右端點值,l表示最小的左端點值 則 s b s a 1 c 轉化成 s a ...
差分約束系統 間隔Intervals
2019 07 10 題目及 偽 題解更新 2021 05 16 我人真的傻了 這已經超出碳基生物的整活範圍了 沒想到時隔多年重學差分約束系統 搜到的題解竟然是兩年前自己打的555我真的是越學越菜 不過 好像貼成樓下樹形dp的了 更新了 tip 翻譯來自谷歌,如有出入請見諒 include incl...
刷題 差分約束 intervals
ai,bi 區間內 和 點集z至少有ci個共同元素,如果用 si 表示區間 0,i 區間內至少有多少個元素的話,那麼sbi sai ci,但是有很多點依然沒有相連線起來 0 si si 1 1 1 差分約束 條件轉化 sum j sum i 1 c i sum i 1 sum j c i i 1 j...