日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

POJ-1201 Intervals---差分约束

發(fā)布時間:2025/4/5 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POJ-1201 Intervals---差分约束 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目鏈接:

https://vjudge.net/problem/POJ-1201

題目大意:

一個整數(shù)集合Z有n個區(qū)間,每個區(qū)間有3個值,ai,bi,ci代表,在區(qū)間[ai,bi]上至少有ci個整數(shù)屬于集合Z,ci可以在區(qū)間內(nèi)任意取不重復(fù)的點。
現(xiàn)在要滿足所有區(qū)間的約束條件,問最少可選多少個點。

Sample Input

5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1

Sample Output

6

思路:

求最小的整數(shù)集合Z滿足| Z ∩ [ ai,? bi ] | >= ci。意思就是在區(qū)間[ai,bi]上至少有ci個整數(shù)屬于集合Z。

可以建模成一個差分約束系統(tǒng)。以輸入的測試數(shù)據(jù)為例進行分析:

設(shè)S[i]是集合Z中小于等于i的元素個數(shù)。那么就有以下不等式組:

(1)Z集合中范圍在[ai, bi]的整數(shù)個數(shù)至少為ci,也就相當(dāng)于S[bi] - S[ai - 1] >= ci

  根據(jù)差分約束系統(tǒng)中的三角不等式(d[v] - d[u] <=? Edge[u][v])

  上述不等式可以轉(zhuǎn)化成S[ai - 1] - S[bi] <= -ci ? ?? 邊:<bi, ai-1> 權(quán)值-ci

? ? 上述例子就有以下不等式組(1)

  S2 - S7 <= -3

  S7 - S10 <= -3

  S5 - S8 <= -1

  S0 - S3 <= -1

  S9 - S11 <= -1

(2)根據(jù)實際情況,還有兩個約束條件

  S[i] - S[i - 1] <= 1

  S[i] - S[i - 1] >= 0,即S[i - 1] - S[i] <= 0

?

最終要求的是什么?

設(shè)所有區(qū)間右端點的最大值為mx,如該測試數(shù)據(jù)中mx = 11, 所有區(qū)間左端點的最小值為mn

如該測試數(shù)據(jù)中mn = 1, mn - 1 = 0

最終要求的是S[mx] - S[mn - 1]的最小值,也就是S[mx] - S[mn - 1] >= M(M的最大值)

也就是S[mn - 1] - S[mx] <= -M(-M的最小值)也就是點mx到點mn-1的最短路-M,答案求的是M

這里需要注意的是源點是mx,終點是mn-1。

所以進行bellman算法時,應(yīng)該從mx出發(fā),求出dist[mn - 1]。(dist數(shù)組保存的是從源點出發(fā)到各點的最短距離)

?

?

但是上述的約束條件太多,最多會達到3*50000條邊,全部轉(zhuǎn)化成邊不是個好方法,所以應(yīng)該進行優(yōu)化:

?

  (1)用上述不等式組(1)進行建圖,源點到各個頂點最短路徑初始為0,因為Si - Smx <=0,所以源點到各個頂點的距離一定會小于等于0,

  (2)用Bellman算法求出源點到各個頂點的最短路徑長度,每次循環(huán)時,判斷完約束條件(1)后,再判斷約束條件(2)和(3)

?

  約束條件(2)的判斷

  S[i] - S[i - 1] <= 1等效于S[i] - S[mx] <= S[i - 1] - S[mx] + 1

  由于上述dist數(shù)組表示從源點出發(fā)到各點的最短距離,所以S[i] - S[mx]就是dist[i]

  上述條件轉(zhuǎn)化成了dist[i] <= dist[i - 1] + 1

  如果dist[i] > dist[i - 1] + 1, 那么修改dist[i] = dist[i - 1] + 1。

  約束條件(3)的判斷

  S[i - 1] <= S[i] 等效于S[i - 1] - S[mx] <= S[i] - S[mx]?

  也就是dist[i - 1] <= dist[i]

  如果dist[i - 1] > dist[i] 那就修改dist[i- 1] = dist[i]

?

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<map> 9 #include<set> 10 #include<sstream> 11 #define MEM(a, b) memset(a, b, sizeof(a)); 12 using namespace std; 13 typedef long long ll; 14 const int maxn = 50000 + 10; 15 const int INF = 0x3f3f3f3f; 16 int T, n, m, cases, tot; 17 int d[maxn]; 18 struct edge 19 { 20 int u, v, w; 21 edge(){} 22 edge(int u, int v, int w):u(u), v(v), w(w){} 23 }; 24 edge a[maxn]; 25 int mx, mn;//mn左區(qū)間最小值,mx右區(qū)間最大值 26 void init() 27 { 28 tot = 0; 29 MEM(d, 0)//初始化源點0到各個頂點的距離,這里的d[mx]永遠(yuǎn)是0,這就是源點 30 mx = 1, mn = INF; 31 } 32 void bellman() 33 { 34 bool update = 1; 35 while(update)//如果有不更新的時候,直接退出 36 { 37 update = 0; 38 for(int i = 0; i < n; i++)//Bellman算法的邊循環(huán) 39 { 40 int u = a[i].u, v = a[i].v, w = a[i].w; 41 if(d[v] > d[u] + w) 42 { 43 update = 1; 44 d[v] = d[u] + w; 45 } 46 } 47 48 //約束條件2的判斷 49 for(int i = mn; i <= mx; i++) 50 { 51 if(d[i] > d[i - 1] + 1) 52 { 53 update = 1; 54 d[i] = d[i - 1] + 1; 55 } 56 } 57 58 //約束條件3的判斷 59 for(int i = mx; i >= mn; i--) 60 { 61 if(d[i - 1] > d[i]) 62 { 63 update = 1; 64 d[i - 1] = d[i]; 65 } 66 } 67 } 68 } 69 int main() 70 { 71 while(cin >> n) 72 { 73 init(); 74 int u, v, w; 75 for(int i = 0; i < n; i++) 76 { 77 scanf("%d%d%d", &u, &v, &w); 78 a[i] = edge(v, u - 1, -w);//建邊 79 mx = max(mx, v); 80 mn = min(mn, u); 81 } 82 //cout<<mx<<" "<<mn<<endl; 83 bellman(); 84 printf("%d\n", -d[mn - 1]); 85 } 86 return 0; 87 }

?

轉(zhuǎn)載于:https://www.cnblogs.com/fzl194/p/8734451.html

總結(jié)

以上是生活随笔為你收集整理的POJ-1201 Intervals---差分约束的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。