差分约束通常用来求不等式组的可行解。
差分约束的步骤:
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 }