算法复习——差分约束(ssoi种树)
题目:
题目描述
为了绿化乡村,H 村积极响应号召,开始种树了。
H 村里有 n 幢房屋,这些屋子的排列顺序很有特点,在一条直线上。于是方便起见,我们给它们标上 1~n 。树就种在房子前面的空地上。
同时,村民们向村长提出了 m 个意见,每个意见都是按如下格式:希望第 li 个房子到第 ri 个房子的房前至少有 ci 棵树。
因为每个房屋前的空地面积有限,所以每个房屋前最多只能种 ki 棵树。
村长希望在满足村民全部要求的同时,种最少的树以节约资金。请你帮助村长。
输入格式
输入文件输入第 1 行,包含两个整数 n,m 。
第 2 行,有 n 个整数 ki。
第 2~m+1 行,每行三个整数 li,ri,ci 。
输出格式
输出 1 个整数表示在满足村民全部要求的情况下最少要种的树。村民提的要求是可以全部满足的。
样例数据 1
输入 [复制]
5 3
1 1 1 1 1
1 3 2
2 4 2
4 5 1
输出
3
样例数据 2
输入 [复制]
4 3
3 2 4 1
1 2 4
2 3 5
2 4 6
输出
8
备注
【样例1解释】
如图是满足样例的其中一种方案,最少要种 3 棵树。
【样例2解释】
如图是满足样例的其中两种方案,左图的方案需要种 9 棵树,右图的方案需要种 8 棵树。可以验证,最少需要种 8 棵树。
【数据范围】
对于30%的数据,0<n≤100,0<m≤100,ki=1;
对于50%的数据,0<n≤2,000,0<m≤5,000,0<ki≤100;
对于70%的数据,0<n≤50,000,0<m≤100,000,0<ki≤1,000;
对于100%的数据,0<n≤500,000,0<m≤500,000,0<ki≤5,000
题解:
在此引用神犇nancheng58的题解,orz··
比较简单的差分约束. 但要注意源点的选取. 由约束条件可得 (1)dis[y+1]-dis[x]>=z. (2)0<=dis[i]-dis[i-1]<=k[i]. 因为是跑最长路. 所以要把(2)式拆成 dis[i]-dis[i-1]>=0. dis[i-1]-dis[i]>=-k[i]. spfa松弛即可
差分约束详解:
比如有这样一组不等式:
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就可以化成小于等于)。这样的不等式组就称作差分约束系统。
这个不等式组要么无解,要么就有无数组解。因为如果有一组解{X1, X2, ..., Xn}的话,那么对于任何一个常数k,{X1 + k, X2 + k, ..., Xn + k}肯定也是一组解,因为任何两个数同时加一个数之后,它们的差是不变的,那么这个差分约束系统中的所有不等式都不会被破坏。
差分约束系统的解法利用到了单源最短路径问题中的三角形不等式。即对于任何一条边u -> v,都有:
d(v) <= d(u) + w(u, v)
其中d(u)和d(v)是从源点分别到点u和点v的最短路径的权值,w(u, v)是边u -> v的权值。
显然以上不等式就是d(v) - d(u) <= w(u, v)。这个形式正好和差分约束系统中的不等式形式相同。于是我们就可以把一个差分约束系统转化成一张图,每个未知数Xi对应图中的一个顶点Vi,把所有不等式都化成图中的一条边。对于不等式Xi - Xj <= c,把它化成三角形不等式:Xi <= Xj + c,就可以化成边Vj -> Vi,权值为c。最后,我们在这张图上求一次单源最短路径,这些三角形不等式就会全部都满足了,因为它是最短路径问题的基本性质。
话说回来,所谓单源最短路径,当然要有一个源点,然后再求这个源点到其他所有点的最短路径。那么源点在哪呢?我们不妨自已造一个。以上面的不等式组为例,我们就再新加一个未知数X0。然后对原来的每个未知数都对X0随便加一个不等式(这个不等式当然也要和其它不等式形式相同,即两个未知数的差小于等于某个常数)。我们索性就全都写成Xn - X0 <= 0,于是这个差分约束系统中就多出了下列不等式:
X1 - X0 <= 0
X2 - X0 <= 0
X3 - X0 <= 0
X4 - X0 <= 0
X5 - X0 <= 0
对于这5个不等式,也在图中建出相应的边。最后形成的图如下:
图中的每一条边都代表差分约束系统中的一个不等式。现在以V0为源点,求单源最短路径。最终得到的V0到Vn的最短路径长度就是Xn的一个解。从图1中可以看到,这组解是{-5, -3, 0, -1, -4}。当然把每个数都加上10也是一组解:{5, 7, 10, 9, 6}。但是这组解只满足不等式组(1),也就是原先的差分约束系统;而不满足不等式组(2),也就是我们后来加上去的那些不等式。当然这是无关紧要的,因为X0本来就是个局外人,是我们后来加上去的,满不满足与X0有关的不等式我们并不在乎。
也有可能出现无解的情况,也就是从源点到某一个顶点不存在最短路径。也说是图中存在负权的圈。这一点就不展开了,请自已参看最短路径问题的一些基本定理。
其实,对于图1来说,它代表的一组解其实是{0, -5, -3, 0, -1, -4},也就是说X0的值也在这组解当中。但是X0的值是无可争议的,既然是以它作为源点求的最短路径,那么源点到它的最短路径长度当然是0了。因此,实际上我们解的这个差分约束系统无形中又存在一个条件:
X0 = 0
也就是说在不等式组(1)、(2)组成的差分约束系统的前提下,再把其中的一个未知数的值定死。这样的情况在实际问题中是很常见的。比如一个问题表面上给出了一些不等式,但还隐藏着一些不等式,比如所有未知数都大于等于0或者都不能超过某个上限之类的。比如上面的不等式组(2)就规定了所有未知数都小于等于0。
对于这种有一个未知数定死的差分约束系统,还有一个有趣的性质,那就是通过最短路径算法求出来的一组解当中,所有未知数都达到最大值。下面我来粗略地证明一下,这个证明过程要结合Bellman-Ford算法的过程来说明。
假设X0是定死的;X1到Xn在满足所有约束的情况下可以取到的最大值分别为M1、M2、……、Mn(当然我们不知道它们的值是多少);解出的源点到每个点的最短路径长度为D1、D2、……、Dn。
基本的Bellman-Ford算法是一开始初始化D1到Dn都是无穷大。然后检查所有的边对应的三角形不等式,一但发现有不满足三角形不等式的情况,则更新对应的D值。最后求出来的D1到Dn就是源点到每个点的最短路径长度。
如果我们一开始初始化D1、D2、……、Dn的值分别为M1、M2、……、Mn,则由于它们全都满足三角形不等式(我们刚才已经假设M1到Mn是一组合法的解),则Bellman-Ford算法不会再更新任合D值,则最后得出的解就是M1、M2、……、Mn。
好了,现在知道了,初始值无穷大时,算出来的是D1、D2、……、Dn;初始值比较小的时候算出来的则是M1、M2、……、Mn。大家用的是同样的算法,同样的计算过程,总不可能初始值大的算出来的结果反而小吧。所以D1、D2、……、Dn就是M1、M2、……、Mn。
那么如果在一个未知数定死的情况下,要求其它所有未知数的最小值怎么办?只要反过来求最长路径就可以了。最长路径中的三角不等式与最短路径中相反:
d(v) >= d(u) + w(u, v)
也就是 d(v) - d(u) >= w(u, v)
所以建图的时候要先把所有不等式化成大于等于号的。其它各种过程,包括证明为什么解出的是最小值的证法,都完全类似
最后补充二点:1.注意源点在题目中的实际意义2.求最大值用最短路,求最小值用最长路
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> #include<queue> using namespace std; const int N=5e5+5; const int INF=0x3f3f3f3f; queue<int>que; int n,m,k,dis[N]; int tot=0,first[N],go[N*4],next[N*4],val[N*4]; bool visit[N]; inline int R() {int i=1,f=0;char c;for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());if(c=='-'){i=-1;c=getchar();}for(;c>='0'&&c<='9';c=getchar())f=(f<<3)+(f<<1)+c-'0';return f*i; } inline void comb(int u,int v,int w) {next[++tot]=first[u],first[u]=tot,go[tot]=v,val[tot]=w; } int main() {// freopen("a.in","r",stdin);memset(dis,-63,sizeof(dis));n=R();m=R();for(int i=1;i<=n;i++){k=R();comb(i,i-1,-k);}for(int i=1;i<=n;i++)comb(i-1,i,0);int l,r,c;for(int i=1;i<=m;i++){l=R();r=R();c=R();comb(l-1,r,c);}dis[0]=0;visit[0]=true;que.push(0);while(!que.empty()){int u=que.front();que.pop();visit[u]=false;for(int e=first[u],v;e;e=next[e]){v=go[e];if(dis[v]<dis[u]+val[e]){ dis[v]=dis[u]+val[e];if(!visit[v])que.push(v);}}}cout<<dis[n]<<endl;return 0; }
转载于:https://www.cnblogs.com/AseanA/p/7201407.html
算法复习——差分约束(ssoi种树)相关推荐
- POJ3169 Layout , 最短路算法解差分约束问题
POJ3169 Layout 题意: n头牛编号为1到n,按照编号的顺序排成一列,每两头牛的之间的距离 >= 0.这些牛的距离存在着一些约束关系:1.有ml组(u, v, w)的约束关系,表示牛 ...
- HDU3440(差分约束+SPFA算法)
题意:两栋房子之间的最大距离为D,也就是A-B<=D,现在求出最矮和最高房子之间的最大距离 思路:差分约束+SPFA算法: 当问题可以转化为形如一组 xi‑x'i<=yi 或一组 xi‑x ...
- 解题报告:P5960 【模板】差分约束算法(及常用技巧)
P5960 [模板]差分约束算法 差分约束系统 给出 n 个变量和 m 个约束条件,形如 xi−xj≤ckx_i - x_j \leq c_kxi−xj≤ck,你需要求出一组解,使得所有约束条件 ...
- 【模板】差分约束算法
[模板]差分约束算法 题意: 题解: 模板题 算法讲解 给出一组包含 m 个不等式,有 n 个未知数.求任意一组满足这个不等式组的解,或判定无解. 连边之后跑最短路,保证每个连通块都没有负环即可. 也 ...
- 【图论】差分约束算法详解
一.前言 在介绍差分约束之前,我们首先需要知道差分约束是用来解决什么问题的:差分约束是一个用来解决形如 X<=Y+c 的二元不等式组的可行解的一个算法.在高中数学中我们会学习如何使用线性规划的方 ...
- 算法提高课-图论-差分约束- AcWing 1169. 糖果:spfa求单源最短路、差分约束
文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 差分约束系统 差分约束系统是一种特殊的N元一次不等式组.它包含N个变量X1,...,XnX_1,...,X_nX1,...,Xn ...
- 洛谷OJ:P5960 【模板】差分约束算法
思路:差分约束模板题,注意使用SPFA来判断负环,也即无解的情况. #include<queue> #include<vector> #include<string> ...
- HDU1531(差分约束+Bellman_ford)
题意:给出一个序列Si = {aSi, aSi+1, ..., aSi+ni} 和其子序列S = {a1, a2, ..., an}:在给出序列的约束条件: aSi + aSi+1 + ... + a ...
- poj1364(差分约束+Bellman-ford)
题意:给出一个序列Si = {aSi, aSi+1, ..., aSi+ni} 和其子序列S = {a1, a2, ..., an}:在给出序列的约束条件: aSi + aSi+1 + ... + a ...
最新文章
- 想挖矿?不如先学习一下以太坊
- Java中Calendar.DAY_OF_WEEK、DAY_OF_MONTH需要减一的原因
- 全球及中国健康保险市场运作模式与需求潜力预测报告2022版
- python中threading模块详解
- HDU 6343.Problem L. Graph Theory Homework-数学 (2018 Multi-University Training Contest 4 1012)
- leetcode259. 较小的三数之和
- python之网络编程1-socket-tcp与udp
- 2019 vs 安装odt_河南2019二级造价师考试教材出版信息,免费送考试大纲
- Javascript中的Math.max()和Math.min()
- Python3 字符串操作
- 【图像隐写】基于matlab WOW算法图像自适应隐写【含Matlab源码 368期】
- 原版98启动盘镜像.img_【教程】利用Windows 10 官方下载工具下载最新系统镜像、制作启动盘...
- ToLua 入门06_LuaCoroutine
- (六)Ps剪切蒙版/图框
- android 图标的格式,Android应用图标适配
- Android 适配时用到的限定词
- 简单的Java 16方格排序游戏
- 计蒜客T1003输出字符菱形
- 在厦门,“隐藏”了一个超高逼格的智慧园区
- Service Mesh发展历程
热门文章
- Docker网络解决方案 - Weave部署记录
- docker(7、容器网络6) weave 网络 Weave 跨主机的连通和隔离特性
- Selenium 如何处理多层嵌套 iframe
- 用VSCode开发Spark应用
- 一个对随机过程的理解
- 计算机在无纸化办公系统中应用属于,福建省闽侯职专计算机基础知识练习题.doc...
- oracle数据库 交集,Oracle两个逗号分割的字符串,获取交集、差集(sql实现过程解析)...
- Linux下保存/不保存退出vi,vim编辑
- 写一篇计算机视觉学习心得
- linux下%3e和%3e%3e的区别,华为nova3和3e的区别