poj 1201 Intervals(差分约束)
做的第一道差分约束的题目,思考了一天,终于把差分约束弄懂了O(∩_∩)O哈哈~
题意(略坑):三元组{ai,bi,ci},表示区间[ai,bi]上至少要有ci个数字相同,其实就是说,在区间[0,50000]上,每一个三元组表示[ai,bi]之间至少要标记ci个数字,问至少要标记多少个数字。
在学习差分约束的童鞋,建议看一下:09年姜碧野的《SPFA算法的优化及应用》,06年冯威的《浅析差分约束系统》,不过后者看起来较难搞懂,也可以看http://ycool.com/post/m2uybbf 写的很不错。
这里写一下我自己的一点心得:
1、差分约束求的是什么?
这里分为两种:求值,判环。
求值:如这道题所示,最终求的是整个区间上被标记点的最小数量,也就是从起点到终点的最小值,不需考虑判环的情况。更广泛的讲,它可以求解不等式的一组解。
判环:poj 1364判断存不存在,即判正负环。
2、差分约束中的松弛操作
举个最短路的例子,1->2 c=3,1->3 c=1,3->2 c=1,即以1为起点,d[2]>d[3]+w(3,2),可以进行松弛。而三条边本身表示的是:a(2)-a(1)<=3,a(3)-a(1)<=1,a(2)-a(3)<=1,我们是从d[]=INF一路更新过来的,用1->3->2这条边更新1->2,实际上表示的是后两个不等式之和a(2)-a(1)<=2比第一个不等式的约束条件更强。
3、最长路与最短路的区别
两者不仅是在三角不等式的表现形式上不同,具体求解的值也不同。
首先要明确,需要额外的一个限定条件:一般为加入源点s,并建立权值为0的边。对于一个不等式组来说,只要有一组解,那么同时加上定值k,仍然满足约束条件。
最短路:d[v]<d[u]+w(u,v),d[i]初始化为INF,而求解出来的是不等式的最大值。何为最大值?若确定其中一个的值,并非能得到每个数的定值,因为是不等式,所以每个值有其取值范围。这里的最大值就是在源点s的限定条件内,所能够取值的上界。仔细思考,这里的最短路只是满足不等式组条件所找到的解,由于最短路是由大到小做松弛操作,找到的最短路即为“最大”。
最长路:d[v]>d[u]+w(u,v),d[i]初始化为-INF,解释同上。这道题目求的是最小值,自然就只能由最长路求解。
4、关于点的数量
如题目所示{ai,bi,ci},[ai,bi]上至少标记ci个点,可以转化为:s(bi)-s(ai-1)>=ci,注意是(ai-1)而非(ai),由于减1的关系,总点数+1。
在判环过程中,SPFA的判定条件为入队n次,其实质是最短路最长经过(n-1)条边,所以入队n次队列仍不为空,即可以判定存在正负环。当点的总数+1,对应的SPFA判环的条件也就变更为cnt[]>n。
5、关于图的连通性
无论是求值,还是判环,原图不构成强连通的前提下都是不能搜索到每一个点的,所以才出现设立一个源点s的方法。事实上,能够到达各个点,更加实用的是在SPFA初始化时,就把所有点加入队列,并把d[i]全部初始化为0。不仅仅是解决了连通的问题,更是避免了错误——加上一个源点s,使总点数为(n+2),SPFA的判环条件必须为cnt[]>(n+1),这是很容易忽视的问题。
这道题由于存在所谓的隐藏条件0<=s(i)-s(i-1)<=1,据此建图已经能够实现图上的连通。
6、不等式的变形
差分约束解决的是>=和<=的问题,若题目给出的是>k(或<k),需要变形。比如若k是整数,>k等价于>=k+1。
7、无穷解,无解。
http://www.cnblogs.com/zstu-abc/archive/2013/08/18.html
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define clr(a,m) memset(a,m,sizeof(a))
using namespace std; const int MAXN=;
const int INF =MAXN; struct Edge{
int v,c,next;
Edge(){}
Edge(int _v,int _c,int _next):v(_v),c(_c),next(_next){}
}edge[MAXN<<]; int head[MAXN],tol;
int d[MAXN],inq[MAXN]; void init()
{
tol=;
clr(head,-);
} void add(int u,int v,int c)
{
edge[tol]=Edge(v,c,head[u]);
head[u]=tol++;
} void SPFA(int down,int up)
{
queue<int>q;
clr(inq,);
rep(i,down,up)
if(i==down)d[i]=;
else d[i]=-INF;
q.push(down);
inq[down]=true;
while(!q.empty())
{
int u=q.front();q.pop();
inq[u]=false;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
int c=edge[i].c;
if(d[v]<d[u]+c){
d[v]=d[u]+c;
if(!inq[v]){
q.push(v);
inq[v]=true;
}
}
}
}
} int main()
{
int n,up=,down=MAXN;
int u,v,c;
scanf("%d",&n); init();
rep(i,,n){
scanf("%d%d%d",&u,&v,&c);
add(--u,v,c);
up=max(up,v);
down=min(down,u);
}
rep(i,down,up){
add(i-,i,);
add(i,i-,-);
}
SPFA(down,up); printf("%d\n",d[up]);
return ;
}
poj 1201 Intervals(差分约束)的更多相关文章
- poj 1201 Intervals(差分约束)
题目:http://poj.org/problem?id=1201 题意:给定n组数据,每组有ai,bi,ci,要求在区间[ai,bi]内至少找ci个数, 并使得找的数字组成的数组Z的长度最小. #i ...
- poj 1201 Intervals——差分约束裸题
题目:http://poj.org/problem?id=1201 差分约束裸套路:前缀和 本题可以不把源点向每个点连一条0的边,可以直接把0点作为源点.这样会快许多! 可能是因为 i-1 向 i 都 ...
- POJ 1201 Intervals (差分约束系统)
题意 在区间[0,50000]上有一些整点,并且满足n个约束条件:在区间[ui, vi]上至少有ci个整点,问区间[0, 50000]上至少要有几个整点. 思路 差分约束求最小值.把不等式都转换为&g ...
- POJ 2101 Intervals 差分约束
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 27746 Accepted: 10687 Description You ...
- POJ 1201 Intervals【差分约束】
传送门:http://poj.org/problem?id=1201 题意: 有n个如下形式的条件:,表示在区间[, ]内至少要选择个整数点.问你满足以上所有条件,最少需要选多少个点? 思路:第一道差 ...
- POJ 1201 Intervals (经典) (差分约束)
<题目链接> 题目大意:给你$n$段区间,$a_i,b_i,c_i$ 表示在 $[a_i,b_i]$ 区间内至少要选择$c_i$个点.现在问你在满足这n个条件的情况下,最少要选多少个点? ...
- 【题解】 POJ 1201 Intervals(差分约束)
懒得复制,戳我戳我 Solution: 这道题就是一个板子题 抽象成第\(a\)至第\(b\)间选择数的个数为\(c\),我们就可以用前缀和来表示,这样就可以得到不等式\(s[b]-s[a-1]> ...
- POJ 1201 Intervals(差分约束 区间约束模版)
关于差分约束详情可阅读:http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html 题意: 给定n个区间[L,R], 每个区间至 ...
- poj 1201 Intervals【差分约束+spfa】
设s为前缀和,首先显然的条件是\[ s_{bi}-s_{ai-1}>=c \],然后隐含的是\[ s_i-s_{i-1}>=0 s_i-s_{i-1}<=1 \] 然后根据差分约束, ...
随机推荐
- c++ 格式化printf
类型为uint64_t的变量,使用printf进行打印时,需要区分操作系统: 64位系统:使用%ld 32位系统:使用%llu #include<stdio.h>#include < ...
- shell date
.查看指定时间的时间戳 查看当前时间 #date +%s 查看指定时间 #date -d -- +%s #date -d +%s .将时间戳转换成date #date -d '1970-01-01 U ...
- Matlab中transpose函数的使用
就是转置的意思,和'一个意思,但是并不重复,因为在cellfun中你无法'这样吧,所以有了这个函数,’只是符号. K>> aa = magic(4) aa = 16 2 3 13 5 11 ...
- NYOJ-32 组合数 AC 分类: NYOJ 2014-01-02 22:21 112人阅读 评论(0) 收藏
#include<stdio.h> int num[100]; int pnum(int n,int v); int mv=0; int main(){ int n,v; scanf(&q ...
- 正确使用stl vecotr erase函数
erase函数要么删作指定位置loc的元素,要么删除区间[start, end)的所有元素. 返回值是指向删除的最后一个元素的下一位置的迭代器 Parameters All parameters ar ...
- PHP对XML添加节点之appendChild()方法讲解
问题如下:<b > <c>test</c> </b>我要在b节点里面添加一个子节点比如说加一个d节点,要实现成<b > <c>t ...
- $('li','div') $('div li') $('div li')
$('div','li')是$(子,父),是从父节点里找子,而不是找li外面的div $('div , li')才是找所有的div和li,之间不存在父子关系 $('div li') 是找div里面所有 ...
- Oracle 体系结构2 - 实例和数据库
Oracle最最基本的概念: 实例和数据库 实例就是oracle进程和一块共享内存, 数据库就是静态的文件,如datafile, log file, redo logfile, control fil ...
- QQ拼音还是不行哇
QQ拼音还是不行啊,虽说没广告,但是很多词条没有,例如知乎.蒋京虎. 泰囧……
- XML中如何使用schema
Schema简介 DTD的语法相当复杂,并且它不符合XML文件的标准,自成一个体系,W3C定义的Schema用来代替DTD. chema相对于DTD的明显好处是XML Schema文档本身也是XML文 ...