初涉差分约束系统

一个把数学问题转化为图论模型的很好的例子

差分约束系统

差分约束系统的定义是:一个由$n$个变量和$m$个约束条件组成,形成$m$个形如$x_i-x_j≤k$的不等式($i,j∈[1,n],k$为常数)的系统。

举个例子(图自网络):

例如这个不等式组就是一个差分约束系统。

我们要求的通常是附加几个条件之后(例如$x_i>0$)的这个系统的最大/小解。因为很容易发现,若只有变量之间的相对限制,这个系统要么是无数解;要么是无解。

那么怎么把这个抽象的不等式组化为图论模型呢?

观察一下这个例子(图仍然来自网络):

这个例子其实就是上面那个不等式组的图论描述。其中图中的边$(u,v,w)$表示$x_v-x_u≤w$。

那么当要求最大值时,就求一遍最短路就好了。

看上去是不是很奇怪,为什么求最大值时要求最短路呢

因为这里的所有约束条件是必须要同时满足的,所以求的最短路就是满足所有条件下的最大值了。

于是就变为了一张图中的最长/短路问题了。

值得注意的是由于差分约束中会有负权,所以应该使用SPFA来解决。

参考:

1.夜深人静写算法(四) - 差分约束

2.BZOJ 2330: [SCOI2011]糖果 [差分约束系统] 【学习笔记】

一些题目

【线性约束】排队

题目描述

有N个人按顺序排成一条直线,满足任何两个人的位置不重合,现在有两种约束:
X约束Ax Bx Cx(1 <= Ax < Bx <= N),表示Ax和Bx的距离小于等于Cx。
Y约束Ay By Cy(1 <= Ay < By <= N),表示Ay和By的距离大于等于Cy。
如果这样的排列存在,输出总和最长距离(无限则输出INF)。
否则如果不存在,输出-1。


题目分析

建图的要点上文已经提到过了,这里讲一下怎么判断无限长。

这里求的是最大值,也就是说我们跑的是最短路。没有最大值等价于没有最短路。

显然没有最短路就是存在负权环,刚好SPFA顺带解决了这个问题。

【区间约束】luoguP1645 序列

题目描述

有一个整数序列,它的每个数各不相同,我们不知道它的长度是多少(即整数个数),但我们知道在某些区间中间至少有多少个整数,用区间(Li,Ri,Ci)来描述,表示这个整数序列中至少有Ci个数来自区间[Li,Ri],给出若干个这样的区间,问这个整数序列的长度最少能为多少?

输入输出格式

输入格式:

第一行一个整数N,表示区间个数;

接下来N行,每行三个整数(Li,Ri,Ci),描述一个区间。

输出格式:

仅一个数,表示该整数序列的最小长度。

【数据规模】

N<=1000,0<=Li<=Ri<=1000,1<=Ci<=Ri-Li+1


题目大意

这里讲一下大致题意(好像是出题人语文不大好写的不是人话?也可能是我语文不好看不懂?)

现在有一个长为1000单位长度的区间,单位长度内要么有一个数,要么什么都没有。

现在知道一些小区间内至少有多少数,求大区间内最少有多少数。

题目分析

区间问题套路:前缀和。

我们对于前缀和进行差分约束。

这里求的是最小值=最长路。

 1 #include<bits/stdc++.h>
 2 const int maxn = 1013;
 3
 4 struct node
 5 {
 6     int y,val;
 7     node() {}
 8     node(int a, int b):y(a),val(b) {}
 9 };
10 int n,m;
11 int dis[maxn];
12 bool vis[maxn];
13 std::vector<node> a[maxn];
14 std::queue<int> q;
15
16 int read()
17 {
18     char ch = getchar();
19     int num = 0;
20     for (; !isdigit(ch); ch = getchar());
21     for (; isdigit(ch); ch = getchar())
22         num = (num<<1)+(num<<3)+ch-48;
23     return num;
24 }
25 void spfa(int s)
26 {
27     q.push(s);
28     memset(dis, -63, sizeof dis);
29     dis[s] = 0;
30     while (q.size())
31     {
32         int tt = q.front();
34         vis[tt] = 0;
35         q.pop();
36         for (unsigned int i=0; i<a[tt].size(); i++)
37             if (dis[a[tt][i].y] < dis[tt]+a[tt][i].val) //最长路
38             {
39                 dis[a[tt][i].y] = dis[tt]+a[tt][i].val;
40                 if (!vis[a[tt][i].y]){
41                     vis[a[tt][i].y] = 1;
42                     q.push(a[tt][i].y);
43                 }
44             }
45     }
46 }
47 int main()
48 {
49     m = read();
50     for (int i=1; i<=m; i++)
51     {
52         int x = read()+1, y = read()+1
53         , z = read();
54         n = std::max(n, y);
55         a[x-1].push_back(node(y, z));
56     }
57     for (int i=1; i<=n; i++)
58         a[i-1].push_back(node(i, 0)),      //相邻前缀和之间也有限制
59         a[i].push_back(node(i-1, -1));  //这是为了避免f[i]=f[i-1]+k(k>1)的情况
60     spfa(0);
61     printf("%d\n",dis[n]);
62     return 0;
63 }

【区间约束】bzoj2330: [SCOI2011]糖果

Description

幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。

Input

输入的第一行是两个整数N,K。

接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。

如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;

如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;

如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;

如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;

如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;

Output

输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。

【数据范围】

对于30%的数据,保证 N<=100

对于100%的数据,保证 N<=100000

对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N


题目分析

看上去稍微复杂了一点?

这里出现了严格的不等式,不过由于这里的所有值都是整数,我们可以将$a<b$变为$a≤b-1$。

再者在建图的地方注意一下、判断一下无解,就可以了。

这里有一篇写得非常好的博客:BZOJ 2330: [SCOI2011]糖果 [差分约束系统] 【学习笔记】,里面有一些非常妙的注意点。

 1 #include<bits/stdc++.h>
 2 const int maxn = 100033;
 3
 4 struct node
 5 {
 6     int y,val;
 7     node() {}
 8     node(int a, int b):y(a),val(b) {}
 9 };
10 int n,k;
11 int dis[maxn],tot[maxn];
12 long long cnt;
13 bool vis[maxn];
14 std::queue<int>    q;
15 std::vector<node> a[maxn];
16
17 int read()
18 {
19     char ch = getchar();
20     int num = 0;
21     for (; !isdigit(ch); ch = getchar());
22     for (; isdigit(ch); ch = getchar())
23         num = (num<<1)+(num<<3)+ch-48;
24     return num;
25 }
26 void end()
27 {
28     puts("-1");
29     exit(0);
30 }
31 bool spfa()
32 {
33     for (int i=1; i<=n; i++)
34     {
35         vis[i] = 1, dis[i] = 1, tot[i] = 1;
36         q.push(i);
37     }
38     while (q.size())
39     {
40         int tt = q.front();
41         vis[tt] = 0;
42         q.pop();
43         for (unsigned int i=0; i<a[tt].size(); i++)
44         {
45             int v = a[tt][i].y, w = a[tt][i].val;
46             if (dis[v] < dis[tt]+w)
47             {
48                 dis[v] = dis[tt]+w;
49                 if (!vis[v]){
50                     vis[v] = 1;
51                     if (++tot[v] > n) return 1;
52                     q.push(v);
53                 }
54             }
55         }
56     }
57     return 0;
58 }
59 int main()
60 {
61     n = read(), k = read();
62     for (int i=1; i<=k; i++)
63     {
64         int tt = read(), x = read(), y = read();
65         if (tt==1 || tt==3)
66             a[y].push_back(node(x, 0));
67         if (tt==1 || tt==5)
68             a[x].push_back(node(y, 0));
69         if (tt==2)
70         {
71             if (x==y) end();
72             else a[x].push_back(node(y, 1));
73         }
74         if (tt==4)
75         {
76             if (x==y) end();
77             else a[y].push_back(node(x, 1));
78         }
79     }
80     if (spfa()) end();
81     for (int i=1; i<=n; i++) cnt += dis[i];
82     printf("%lld\n",cnt);
83     return 0;
84 }

【未知条件约束】poj1275Cashier Employment

题目链接:http://poj.org/problem?id=1275

现在还不会……

END

原文地址:https://www.cnblogs.com/antiquality/p/9047927.html

时间: 2024-10-07 07:49:44

初涉差分约束系统的相关文章

差分约束系统

差分约束系统是指一系列不等式: $$ X_j - X_i \le C_{ij}(1\le i, j \le n) $$ 当然 i,j 不必取遍 1-n,而且在扩展的状况下,对于每个(i,j),可以由多个 $C_{ij}$,但是我们很容易把它们化成一个不等式. 在求解不等式组之前,我们可以分析一下这个不等式组的性质. 1. 这个不等式组是可以无解的,比如: $$X_1 - X_2 \le -1 \\ X_2 - X_3 \le -1 \\ X_3 - X_1 \le -1$$ 否则三个不等式相加得

UVa 515 - King (差分约束系统 + SPFA求带负权最短路)

下面是差分约束系统的详细介绍,以及解决方法~ 摘抄自 xuezhongfenfei(他好像也是转的....) 差分约束系统 X1 - X2 <= 0 X1 - X5 <= -1 X2 - X5 <= 1 X3 - X1 <= 5 X4 - X1 <= 4 X4 - X3 <= -1 X5 - X3 <= -3 X5 - X4 <= -3 不等式组(1) 全都是两个未知数的差小于等于某个常数(大于等于也可以,因为左右乘以-1就可以化成小于等于).这样的不等式组

差分约束系统 初见

今天初次学习差分约束系统,很神奇的东西 定义: 如果一个系统由n个变量和m个约束条件组成,其中每个约束条件形如xj-xi<=bk(i,j∈[1,n],k∈[1,m]),则称其为差分约束系统(system of difference constraints).亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法. 求解差分约束系统,可以转化成图论的单源最短路径(或最长路径)问题. 其实在一些问题中需求最小值或最大值,同时需要满足一系列的不等式关系,这样就可以用到差分约束系统了,对于求最小值的问

ZOJ 3668 Launching the Spacecraft (差分约束系统,最短路)

题目: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3668 题意: 给一个初始值为0的长度为n的区间,给m个约束l,r,a,b,表示从l到r的区间和>=a且<=b,且每个数的范围为-10000~10000,问这个区间的每个数是多少,要求数尽可能大,且序列字典序最大. 方法: 差分约束系统,以前缀和表示一个节点a[i] 建图:根据下面约束条件建图 a[i]-a[i-1]<=10000 a[i-1]-a[i]&l

POJ 2983 Is the Information Reliable?(差分约束系统)

题目地址:POJ 2983 这题刚上来完全不知道跟差分约束系统有什么关系.....后来发现只要判个负环就可以.. 因为假如有冲突的话会形成一个负环.之所以建图加上一个正值一个负值,是因为这样的话,像1 2 4和1 2 3这样的数据就会形成一个负环.这个方法还是很巧妙的...然后对于V的那些不清楚的位置,就会跟P的那些等式联立形成一个不等式,然后在用最短路判环的过程中就用松弛来解决. 代码如下: #include <iostream> #include <cstdio> #inclu

【POJ 1201】 Intervals(差分约束系统)

[POJ 1201] Intervals(差分约束系统) 11 1716的升级版 把原本固定的边权改为不固定. Intervals Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23817   Accepted: 9023 Description You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn. Write a p

差分约束系统--详讲

------------差分约束题目请戳:差分约束题集暨报告 总的开说差分约束问题就是给出一系列不等式然后求问某一式子的最大值或者最小值. 差分约束问题具体解释: 比方有这样一组不等式: X1 - X2 <= 0 X1 - X5 <= -1 X2 - X5 <= 1 X3 - X1 <= 5                   不等式组(1) X4 - X1 <= 4 X4 - X3 <= -1 X5 - X3 <= -3 X5 - X4 <= -3 全都是

浅谈差分约束系统——图论不等式的变形

浅谈差分约束系统——图论不等式的变形 ----yangyaojia 版权声明:本篇随笔版权归作者YJSheep(www.cnblogs.com/yangyaojia)所有,转载请保留原地址! 一.定义 如若一个系统由n个变量和m个不等式组成,并且这m个不等式对应的系数矩阵中每一行有且仅有一个1和-1,其它的都为0,这样的系统称为差分约束( difference constraints )系统. 二.分析 简单来说就是给你n个变量,给m个形如x[i]-x[j]≥k①或x[i]-x[j]≤k②.求两

UVA11478 Halum [差分约束系统]

https://vjudge.net/problem/UVA-11478 给定一个有向图,每条边都有一个权值.每次你可以选择一个结点v和一个整数d,把所有以v为终点的边的权值减小d,把所有以v为起点的边的权值增加d,最后让所有边的权值的最小值大于零且尽量大. 该死书上翻译错了 >0不是非负 WA好几次因为这个 考虑每条边的约束,di表示i的halum量 w-dv+du>0 dv-du<w 但求解这个差分约束系统只是让这组不等式成立,最长路和最短路控制的都是单个d的最值而不是最小值最大 那