差分约束

时间:2019-12-02
本文章向大家介绍差分约束,主要包括差分约束使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

差分约束通常用来求不等式组的可行解。

差分约束的步骤:

1.先将每个不等式xi <= xj + w,转化成一条从xj走到xi的长度为w的一条边。

2.找一个超级源点,使得从该源点开始可以遍历所有边。

3.从源点开始求一遍单源最短路,如果存在负环,则原不等式无解,如果没有负环,则dis[i]就是原不等式的一个可行解。

差分约束求不等式组最大值最小值:

如果求最小值,则应该求最长路,求最大值,应该求最短路。

如果没有一个超级源点可以遍历所有边,就自己设置一个超级源点。

求xi的最大值:求所有从xi出发,形成不等式xi <= xj + w1 <= xk + w1 ...<= w1 + w2 + w3 ...+ w所计算出的上界,xi的最大值等于所有上界的最小值。

 

银河

由题求得是最小值。所以用最长路。

根据题意:

1.当T  = 1,A >= B, B >= A。

2.当T = 2,  B >= A + 1。

3.当T = 3,A >= B。

4.当T = 4,  A >= B + 1。

5.当T = 5,B >= A。

从0向所有的点连一条长度为1的 边,即Xi >= 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 }

原文地址:https://www.cnblogs.com/1-0001/p/11973597.html