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