差分约束系统解析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
差分约束系统poj1201 ,poj1275的解题报告
现在发现刘汝佳写的书真的是给高手看的!。要是一个半懂的人去看这本书根本不知所云。简直就是晦涩难懂。但是一旦把问题搞懂了再去看,就发现居然这个书全讲的是重点。看来这本书只适合于做指导用。我基本上没怎么看懂这个书。
这几天做差分系统的题的时候,经常碰到这种情况:
为什么题目明明要求的是求某某值的最小值。但找的资料上却说的用最长路求法。还有的地方要求某函数值的最大值,但用的方法却是求最短路的方法。
到底是求最短路还是求最长路?
最终我发现了。只要是能用bellman_ford解决的差分约束系统,既可以用最长路求法求得,也可以用最短路求得。并且部分可以用Dijkstra解决!
其实个人觉得用“单原点最短路,单原点最长路求法”这个两个说法来描述用bellman_ford 解决差分约束系统是不准确的。在一般的最短路径求法中对应的松弛操作为:
If dist[b]》dist[a]+ w[a][b] then
dist[b]= dist[a]+ w[a][b]。。。。。。。。。。。。。。。。。。。。。。。。。。。(1)
然而在所谓的最长路求法中松弛操作变为了
If dist[b]《dist[a]+ w[a][b] then
dist[b]= dist[a]+ w[a][b]。。。。。。。。。。。。。。。。。。。。。。。。。。。(2)
也就是说,最短路就是对应(1)号松弛方法,最长路对应(2)号而已。
现在先来看看一般的例子:
假如有如下不等式组:(即求出来的最终答案要保证下列不等式成立)
s[bi] -s[ai]>= ci; 0<=ai,bi<= max; i=1,2,3,。。。。
现在求s[max]的最小值.
用求最长路的方法:即用(2)号松弛方法
先将不等式变形:s[bi]>=s[ai]+ci;
即保证s[bi] 不小于s[ai]+ci;
而(2)号松弛操作的作用也是这个。即保证dist[b]不小于dist[a]+ w[a][b]
于是这个个不等式便与这种松弛操作统一了。
所以就设a到b的路径为ci。应用(2)号松弛操作得到的最后答案,就能保证不等式始终是成立的。
因此对所有s[bi] -s[ai]>= ci; 设ai到bi的距离为ci,其余没有路径的地方设为—10000000000000000(无穷小)原点到自己的距离设为0;
于是bi被不断跟新。不断变大。
注意这个时候s[bi]是从负无穷小慢慢升上来的。到最后计算完成后,事实上对于某些不等式有s[bi] > s[ai]+ci。但有一条最终路径(即最长路径)上的节点是完全符合s[bi] = s[ai]+ci的
所以这个时候求到的s[max]是所有可行解中的最小值。
下面改用(1)号松弛方法。
(1)号的作用就是保证dist[b]不大于dist[a]+ w[a][b]
将不等式组变形:s[ai]-s[bi]<=-ci;再变:s[ai]<=s[bi] + (—ci)
于是(1)号松弛操作也与不等式统一了。
即我们设bi 到ai 的路径为(-ci)
用一号松弛法的算法,求最短路径。因为是求最短路径,对于没有路径的地方
设为100000000000000(无穷大);
当算法进行时:于是s[ai]的值被不断跟新,不断缩小。最终到达的最短路径的。所以s[max]是所有可行解中的最小值!只不过这个时候求出的最小值与刚才求得那个最小值为相反数:这是因为:
差分约束系统构成的图一般是有向图。求最长路(即2号松弛)是求原点到终点的距离。而我们设原点到自己的路径为0.所以求出来的最长路径为正。
而如果反过来求最短路,画下图的话就会明白。求的是终点到原点的距离。如果原点自己到自己为0的话,且这些距离都为负。所以求出来的结果是负的。反个号就是答案了。
至此,对于同一个差分约束系统所谓的求最短路,求最长路都是可以行得通的,只不过看你怎么变化不等式。从而最终选择相应的松弛操作而已。
假如题目再变一下。求s[max]的最大值呢?。如果一定要用(1)号松弛法(即求最长路),当然前提是不等式有对s[max]进行约束。
用同样的方法,同样的不等式求出来的最大值,最小值难道是一样的吗。
注意,因为差分约束图是有向图。如果求最大值的话,则不等式
s[bi] -s[ai]>= ci; 中有很大一部分是bi
也就是说这个求得最大值是从终点到原点的最长路径!而不是原点到终点的最长路径!。
这两种方向都不一样。因此。即使是一样的图。但求出来的东西不一样。
最后,不等式必须是大于等于,或者小于等于号。才能正常运行。因为我们求出来的最终某条路径,其路径上的所有节点是完全符合= 关系的。只是对于其他路径才符合不等关系
下面举例说明:poj1201
题目分析:给出N个区间以及每个区间对应的整数,计算一个集合,使得对于每个给出的区间,集合与它的相同元素个数不小于相应的整数。那么这个集合最小为多少?
输入:N行,每行三个整数:A B C,代表区间的两个端点,以及相应整数(最小共同元素数)
对于最长路径求法有不等式:s[i]表示0.。。I-1.已有多少个整数了。
s[b+1]-s[a]>=c;
将所有点排序后得一次将区间端点排序
s[i]-s[i-1]>= 0;
s[i-1]-s[i]>=-val(s[i-1]-s[i]) 。。。。。。。。V al(s[i-1]-s[i])代表两个端点的差值
于是图就建好了,同时注意约束s[max]的是它前面那个点。也就是说求的是原点到s[max]的最长路径。同时设原点自己到自己为0.最后求得s[max]就是答案了。
#include
using namespace std;
const int MAX_M=50000+2;
struct Map{
int a ,b,lon;
};
Map map[6*MAX_M];
int hash[MAX_M];
int cmp( const void *p ,const void *q)
{
return ((Map *)p)->a - ((Map *)q)->a;
}
void spfa(int &ans){