题目:

题目描述

为了绿化乡村,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种树)相关推荐

  1. POJ3169 Layout , 最短路算法解差分约束问题

    POJ3169 Layout 题意: n头牛编号为1到n,按照编号的顺序排成一列,每两头牛的之间的距离 >= 0.这些牛的距离存在着一些约束关系:1.有ml组(u, v, w)的约束关系,表示牛 ...

  2. HDU3440(差分约束+SPFA算法)

    题意:两栋房子之间的最大距离为D,也就是A-B<=D,现在求出最矮和最高房子之间的最大距离 思路:差分约束+SPFA算法: 当问题可以转化为形如一组 xi‑x'i<=yi 或一组 xi‑x ...

  3. 解题报告:P5960 【模板】差分约束算法(及常用技巧)

    P5960 [模板]差分约束算法 差分约束系统 给出 n 个变量和 m 个约束条件,形如 xi−xj≤ckx_i - x_j \leq c_kxi​−xj​≤ck​,你需要求出一组解,使得所有约束条件 ...

  4. 【模板】差分约束算法

    [模板]差分约束算法 题意: 题解: 模板题 算法讲解 给出一组包含 m 个不等式,有 n 个未知数.求任意一组满足这个不等式组的解,或判定无解. 连边之后跑最短路,保证每个连通块都没有负环即可. 也 ...

  5. 【图论】差分约束算法详解

    一.前言 在介绍差分约束之前,我们首先需要知道差分约束是用来解决什么问题的:差分约束是一个用来解决形如 X<=Y+c 的二元不等式组的可行解的一个算法.在高中数学中我们会学习如何使用线性规划的方 ...

  6. 算法提高课-图论-差分约束- AcWing 1169. 糖果:spfa求单源最短路、差分约束

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 差分约束系统 差分约束系统是一种特殊的N元一次不等式组.它包含N个变量X1,...,XnX_1,...,X_nX1​,...,Xn​ ...

  7. 洛谷OJ:P5960 【模板】差分约束算法

    思路:差分约束模板题,注意使用SPFA来判断负环,也即无解的情况. #include<queue> #include<vector> #include<string> ...

  8. HDU1531(差分约束+Bellman_ford)

    题意:给出一个序列Si = {aSi, aSi+1, ..., aSi+ni} 和其子序列S = {a1, a2, ..., an}:在给出序列的约束条件: aSi + aSi+1 + ... + a ...

  9. poj1364(差分约束+Bellman-ford)

    题意:给出一个序列Si = {aSi, aSi+1, ..., aSi+ni} 和其子序列S = {a1, a2, ..., an}:在给出序列的约束条件: aSi + aSi+1 + ... + a ...

最新文章

  1. 想挖矿?不如先学习一下以太坊
  2. Java中Calendar.DAY_OF_WEEK、DAY_OF_MONTH需要减一的原因
  3. 全球及中国健康保险市场运作模式与需求潜力预测报告2022版
  4. python中threading模块详解
  5. HDU 6343.Problem L. Graph Theory Homework-数学 (2018 Multi-University Training Contest 4 1012)
  6. leetcode259. 较小的三数之和
  7. python之网络编程1-socket-tcp与udp
  8. 2019 vs 安装odt_河南2019二级造价师考试教材出版信息,免费送考试大纲
  9. Javascript中的Math.max()和Math.min()
  10. Python3 字符串操作
  11. 【图像隐写】基于matlab WOW算法图像自适应隐写【含Matlab源码 368期】
  12. 原版98启动盘镜像.img_【教程】利用Windows 10 官方下载工具下载最新系统镜像、制作启动盘...
  13. ToLua 入门06_LuaCoroutine
  14. (六)Ps剪切蒙版/图框
  15. android 图标的格式,Android应用图标适配
  16. Android 适配时用到的限定词
  17. 简单的Java 16方格排序游戏
  18. 计蒜客T1003输出字符菱形
  19. 在厦门,“隐藏”了一个超高逼格的智慧园区
  20. Service Mesh发展历程

热门文章

  1. Docker网络解决方案 - Weave部署记录
  2. docker(7、容器网络6) weave 网络 Weave 跨主机的连通和隔离特性
  3. Selenium 如何处理多层嵌套 iframe
  4. 用VSCode开发Spark应用
  5. 一个对随机过程的理解
  6. 计算机在无纸化办公系统中应用属于,福建省闽侯职专计算机基础知识练习题.doc...
  7. oracle数据库 交集,Oracle两个逗号分割的字符串,获取交集、差集(sql实现过程解析)...
  8. Linux下保存/不保存退出vi,vim编辑
  9. 写一篇计算机视觉学习心得
  10. linux下%3e和%3e%3e的区别,华为nova3和3e的区别