差分约束
差分约束通常用来求不等式组的可行解。
差分约束的步骤:
1.先将每个不等式$x_i\leq x_j + w$,转化成一条从$x_j$走到$x_i$的长度为$w$的一条边。
2.找一个超级源点,使得从该源点开始可以遍历所有边。
3.从源点开始求一遍单源最短路,如果存在负环,则原不等式无解,如果没有负环,则$dis[i]$就是原不等式的一个可行解。
差分约束求不等式组最大值最小值:
如果求最小值,则应该求最长路,求最大值,应该求最短路。
如果没有一个超级源点可以遍历所有边,就自己设置一个超级源点。
求xi的最大值:求所有从$x_i$出发,形成不等式$x_i\leq x_j + w_1\leq x_k + w_1 \cdot \cdot \cdot \leq w_1 + w_2 + w_3 ...+ w$所计算出的上界,$x_i$的最大值等于所有上界的最小值。
银河

由题求得是最小值。所以用最长路。
根据题意:
1.当$T = 1,A \geq B, B >= A$。
2.当$T = 2, B \geq A + 1$。
3.当$T = 3,A \geq B$。
4.当$T = 4, A \geq B + 1$。
5.当$T = 5,B \geq A$。
从0向所有的点连一条长度为1的 边,即$X_i \geq 0 + 1$。
代码:
1 #include <algorithm> 2 #include <cstring> 3 #include <stack> 4 5 using namespace std; 6 7 typedef long long LL; 8 9 const int N = 100010, M = 300010; 10 int e[M], ne[M], h[M], w[M], idx; 11 int st[N], cnt[N]; 12 LL dis[N]; 13 int n, m; 14 15 void add(int a, int b, int c) 16 { 17 e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; 18 } 19 20 bool spfa() 21 { 22 memset(dis, -0x3f, sizeof dis); 23 stack<int> q; 24 25 dis[0] = 0; 26 st[0] = true; 27 q.push(0); 28 29 while(q.size()) 30 { 31 int t = q.top(); 32 q.pop(); 33 34 st[t] = false; 35 36 for(int i = h[t] ; ~i ; i = ne[i]) 37 { 38 int j = e[i]; 39 if(dis[j] < dis[t] + w[i]) 40 { 41 dis[j] = dis[t] + w[i]; 42 cnt[j] = cnt[t] + 1; 43 if(cnt[j] >= n + 1)return false; 44 if(!st[j]) 45 { 46 q.push(j); 47 st[j] = true; 48 } 49 } 50 } 51 } 52 return true; 53 } 54 55 int main(){ 56 cin >> n >> m; 57 memset(h, -1, sizeof h); 58 59 while(m --) 60 { 61 int c, a, b; 62 cin >> c >> a >> b; 63 if(c == 1)add(a, b, 0), add(b, a, 0); 64 else if(c == 2)add(a, b, 1); 65 else if(c == 3)add(b, a, 0); 66 else if(c == 4)add(b, a, 1); 67 else add(a, b, 0); 68 } 69 70 for(int i = 1 ; i <= n ; i ++)add(0, i, 1);//从0向所有点连边 71 72 if(!spfa())puts("-1"); 73 else 74 { 75 LL ans = 0; 76 for(int i = 1 ; i <= n ; i ++)ans += dis[i]; 77 cout << ans << endl; 78 } 79 80 return 0; 81 }

浙公网安备 33010602011771号