算法提高课-图论-差分约束- AcWing 1169. 糖果:spfa求单源最短路、差分约束
文章目錄
- 題目分析
- 題目鏈接
題目分析
來源:acwing
分析:
差分約束系統
差分約束系統是一種特殊的N元一次不等式組。它包含N個變量X1,...,XnX_1,...,X_nX1?,...,Xn? 以及M個約束條件,每個約束條件都是由兩個變量作差構成的,形如Xi?Xj≤ckX_i-X_j \leq c_kXi??Xj?≤ck?,其中ckc_kck?是常數,我們要解決的問題是:求得一組X的解,值得所有約束條件都得到滿足。
對約束條件Xi?Xj≤ckX_i-X_j \leq c_kXi??Xj?≤ck?進行變形,就可以得到Xi≤Xj+ckX_i \leq X_j+c_kXi?≤Xj?+ck?,這與單源最短路徑問題中的三角不等式dist[y]≤dist[x]+zdist[y] \leq dist[x] + zdist[y]≤dist[x]+z很相似。因此,可以把每個變量XiX_iXi?看作有向圖中的一個結點i,對于每個約束條件Xi?Xj≤ckX_i-X_j \leq c_kXi??Xj?≤ck?,從結點j向結點i連一條長度為ckc_kck?的有向邊。
所以說,每個差分約束問題可以轉換為圖論的單源最短路問題。
單源最短路徑中源點需要滿足的條件:
從源點出發,必須可以遍歷到所有的邊。因為只有這樣才能滿足上述的三角不等式。
求解步驟:
如果存在負環,則原不等式組一定無解。
如果無負環,則dist[]數組就是原不等式組的一個可行解。
對應到本題。
求的是最小值,要用最長路。
ac代碼
#include<bits/stdc++.h> using namespace std; typedef long long LL;const int N = 100100, M = 300010; int n, m; int h[N], e[M], w[M], ne[M], idx; LL dist[N]; int q[N], cnt[N]; // 用來求正環 bool st[N];void add(int a, int b, int c){e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; }bool spfa(){int hh = 0, tt = 1;memset(dist, -0x3f, sizeof dist);dist[0] = 0; // 0號點是超級源點q[0] = 0;st[0] = true;while(hh != tt){int t = q[ -- tt]; // 用棧優化st[t] = false;for(int i = h[t]; ~i; i = ne[i]){int j = e[i];if(dist[j] < dist[t] + w[i]){dist[j] = dist[t] + w[i];cnt[j] = cnt[t] + 1;if(cnt[j] >= n + 1) return false;if(!st[j]){q[tt ++] = j;st[j] = true;}}}}return true; }int main(){memset(h, -1, sizeof h);cin >> n >> m;if(m == 0){cout << n << endl;return 0;}for(int i = 1; i <= n; i ++) add(0, i, 1);while( m --){int x, a, b;cin >> x >> a >> b;if( x == 1) add(b, a, 0), add(a, b, 0);else if(x == 2) add(a, b, 1);else if( x == 3) add(b, a, 0);else if( x == 4) add(b, a , 1);else add(a, b, 0);}if(!spfa()) puts("-1");else{LL res = 0;for(int i = 1; i <= n; i ++) res += dist[i];cout << res << endl;} }題目鏈接
https://www.acwing.com/problem/content/1171/
總結
以上是生活随笔為你收集整理的算法提高课-图论-差分约束- AcWing 1169. 糖果:spfa求单源最短路、差分约束的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSP认证201809-2买菜[C++题
- 下一篇: 算法提高课-图论-负环-AcWing 9