首页 > 其他分享 >关于差分约束的一切

关于差分约束的一切

时间:2024-04-09 12:45:43浏览次数:12  
标签:le 一切 不等式 源点 差分 约束 cases 式子 dis

观前须知

笔者的博客主页

声明

本文使用 CC BY-NC-SA 4.0 许可

本文为笔者在 OI 学习中的复习向学习笔记。
部分内容会比较简略。
如有好的习题会不断补充。

知识简介

差分约束解决这样一类问题:
给定一个 n 元一次不等式组,让你求出一组解/判定是否有解/算出某个数的最值/算出和的最值……
先从最简单的开始:

P5960 【模板】差分约束

那么怎么做呢?
发现对于形如 \(x_i - x_j \le c\) 的一个不等式可变形为 \(x_i \le x_j + c\)。
对于一个这样的不等式组:

\[\begin{cases} x_1 \le x_2 + c_1 \\ x_2 \le x_3 + c_2 \\ x_1 \le x_3 + c_3 \\ \end{cases} \]

可以推出 \(x_1 \le x_3 + \min(c_1 + c_2,c_3)\)。
联想一下,这个式子有什么意义呢?

来看这张图:
三角不等式

不难发现,有 \(x_1 \le x_3 + \operatorname{Dis}(x_1,x_3)\)
那么我们可以把三个变量转换为三个点,对于每个约束两个变量关系的不等式,变为图上的一条边!
考虑最短路中的这个式子: \(dis_v \le dis_u + w\)
那么一个形如 \(x_i - x_j \le c\) 即 \(x_i \le x_j + c\) 的式子,
就可以变成图上一条从 \(j\) 指向 \(i\),权值为 \(c\) 的边!
同理,一个形如 \(x_i - x_j \ge c\) 的式子, 可以变为一条从 \(i\) 指向 \(j\),权值为 \(-c\) 的边。
那么图就可以建出来了。
(如果涉及到 \(x_i - x_j < c\) 的式子,可以考虑变为 \(x_i - x_j <= c - 1\) 处理)

值得一提的一个性质
一个这样的不等式组要不然无解,要不然有无数多组解
因为只要有一组解 \(\{ x_1,x_2,x_3,\cdots,x_n\}\),
我们对于每个变量都加上一个相同的值变为 \(\{ x_1+d,x_2+d,x_3+d,\cdots,x_n+d\}\),
不难发现仍然是满足原不等式组的。
那么现在考虑什么情况下无解。

对于这样一个不等式组:

\[\begin{cases} x_1 - x_2 \le 3\\ x_2 - x_3 \le -5\\ x_3 - x_1 \le 1\\ \end{cases} \]

由第一个和第二个不等式相加可以推出 \(x_1 - x_3 \le -2\),
然而再和第三个不等式相加一下会变成 \(0 \le -1\),显然无解。
扩展一下,对于这样一个不等式组:

\[\begin{cases} x_1 - x_2 \le c_1\\ x_2 - x_3 \le c_2\\ \vdots\\ x_{n-1} - x_n \le c_{n-1}\\ x_n - x_1 \le c_n \end{cases} \]

把这 n 个不等式全部相加会变成 \(0 \le \sum c_i\),当且仅当 \(\sum c_i < 0\)时无解。
那么可以发现,这在图上对应了一个负环
所以当且仅当建出来的图上存在负环时无解
判负环用 SPFA,对于不连通的图,添加一个超级源点
从超级源点向所有点连权值为 \(0\) 的边,然后从超级源点跑最短路即可。
若无负环,跑出来的 dis 数组即为一组解。

那么这道板子题,我们就解决了。
代码见:笔者的板子库

但是还不够。
当我们固定源点的值后,我们就可以求出所有点与源点的差的最值
最小值,则跑最长路,求出一个 \(dis_u \ge x\) 的下界。
(这里最长路可以把图的边权全部取相反数,再跑最短路算出)
最大值,则跑最短路,求出一个 \(dis_u \le x\) 的上界。

如果要求所有变量和的最值呢?
例如令所有变量都为非负整数,求最小的变量和(见下面的习题)。
求最小值,我们跑最长路。
一个 \(x_i \ge x_j + c\) 的式子,变为图上一条从 \(j\) 连向 \(i\),权值为 \(c\) 的边(与小于号的形式类似)
建立超级源点,向各点连权值为 \(0\) 的边,并钦定该源点的值为 \(0\) (在代码里体现为dis[0] = 0),相当于让各个点的值都非负。
接下来从超级源点跑最长路,发现 dis 数组正好就是每个点能取的最小值,求和即为答案。

总结一下
由于通常要跑 SPFA,所以差分约束的数据范围一般不会太大。
先确定要跑什么路,再建图。
重点在于建图的时候不要漏掉题目中的隐藏条件

习题

YbtOj 1509 Intervals

对于 \(0\) 到 \(5\times 10^4\) 的每个值建一个变量 \(s_i\) 表示前缀和。
则题目中的条件可变为 \(s_b - s_{a-1} \ge c\)。
注意隐藏条件:\(s_i \le s_{i+1}\) 以及 \(s_{i+1} - s_i \le 1\)。
建超级源点跑最长路,答案即为 \(s_{5\times 10^4}\)

细节:
由于有 \(s_{-1}\) 存在,对于所有节点编号加一再建图。

Luogu P3275 【SCOI2011】 糖果

求最小变量和,跑最长路。
根据题意建图,对于 \(x_a < x_b\) 的条件变为 \(x_a \le x_b - 1\)。
见超级源点跑最长路,答案为 \(\sum dis_i\)。

这道题数据范围较大,差分约束会被 Hack 掉
然而笔者特判自环 + SPFA SLF-swap优化冲过去了

USACO 05DEC Layout G

令 \(d_i\) 表示前缀距离。
按照题意建图,隐藏条件 \(d_i - d_{i+1} \le 0\)。
建超级源点跑最短路,有负环则无解。
对于 1 号节点跑最短路,若与 n 号节点联通则 \(dis_n\) 即为答案,否则两点间距离可以任意大。

标签:le,一切,不等式,源点,差分,约束,cases,式子,dis
From: https://www.cnblogs.com/Sugar-Cube/p/18123724

相关文章

  • 【蓝桥·算法双周赛 第 9 场 小白入门赛】字符迁移【算法赛】题解(字符串+模运算+差分)
    思路差分数组是一种特殊的数组,它的第iii个数定义为原数组的第ii......
  • 简单处理——二值化(钢笔画)和差分化(浮雕画)
    简单处理——二值化(钢笔画)和差分化(浮雕画)一、钢笔画和浮雕画​ RGB转灰度图就类似于英语学习中的abandon,在熟悉了YCbCr等颜色空间以及简单的图像反转之后,我们可以将目光移向今天的主题——二值化和差分化;​ 二值化概念比较简单,就是你给灰度在0—255的灰度图像设置一个阈值,大于......
  • 关于基环树的一切
    观前须知笔者的博客主页声明本文使用CCBY-NC-SA4.0许可。本文为笔者在OI学习中的复习向学习笔记。部分内容会比较简略。如有好的习题会不断补充。知识简介定义基环树是一个有\(n\)个点\(n\)条边的连通图。因为树有\(n\)个点\(n-1\)条边。所以基环树可以......
  • 差分和前缀和——蓝桥杯备赛
    一、大学里的树木要打药问题描述教室外有N棵树,根据不同的位置和树种,学校要对其上不同的药。因为树的排列成线性,且非常长,我们可以将它们看作一条直线给他们编号。树的编号从0∼N−1且N<1e6。对于树的药是成区间分布,比如3∼5号的树靠近下水道,所以他们要用驱蚊虫的药,20......
  • 差分
    前言学习差分前一定要先学习前缀和,因为差分就是前缀和的一个逆运算(有点像微分和积分),所以只有先搞清楚前缀和才能明白差分点这里补习前缀和这里同样也是从一维和二维两个角度去分析差分这个算法正文我们要先理清差分的含义:注意关系,这里跟前缀和里举的例子有差别,b的前缀和数组......
  • 关于树的直径的一切
    观前须知本文使用CCBY-NC-SA4.0许可本文所有详细证明可见OIWiki笔者的博客主页正文定义树的直径指树上任意两点间距离的最大值两次DFS先以任意点为根找到最远点\(v\)再以\(v\)为根找到最远点\(u\)\(u-v\)即为该树的一条直径适用范围:无负权树证明:当\(v\)......
  • 差分约束
    前言考虑单源最短路的一个性质:在有向图中,若存在边\(u\tov\),边权为\(w\),则\(\mathit{dis}_u+w\ge\mathit{dis}_v\)。正确性是显然的,因为如果反之\(\mathit{dis}_u+w<\mathit{dis}_v\),我们就可以令\(\mathit{dis}_v\gets\mathit{dis}_u+w\),原先的就不是最短路了,与题设矛盾......
  • MySQL-相关约束
    MySQL-约束前提:防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息。为了保证数据的完整性,SQL规范以约束的方式对表数据进行额外的条件限制。有以下考虑要点:①实体完整性(EntityIntegrity):例如,同一个表中,不能存在两条完全相同无法区......
  • P5960 【模板】差分约束
    原题链接题解我一直苦苦思考为什么要建边,现在我明白了,如果令\(x_i\)代表离源点的最短路径长度的话,建边之后,\(x_i-x_j<=y_k\)一定成立只有当出现负环的时候说明条件出现了矛盾太神了code#include<bits/stdc++.h>usingnamespacestd;queue<int>q;intin_q[5005]={0};......
  • 生信小白菜之关于mutate函数的一切
    RforDataScience准备包和示例数据library(dplyr)library(nycflights13)mutate()函数基本用法#作用是添加新列,新列是由原有数据计算的来#添加的新列在数据集的最后#举例flights_sml<-select(flights,year:day,ends_with("delay"),distance,air_time)mu......