差分约束系统【变相的最短路】

        之前没有细看,想不明白这个问题怎么和最短路扯上关系,细细看了看,,也没明白,,原因是在看Dijk算法的时候就没好搞明白它的代码实现,以至于这个问题类比到最短路实现的时候一脸懵,还去瞅了瞅三角不等式是什么东西,简单来说,难就难在图的构造上面,构造好图之后就是模板,就是之前的内容了,一起看看这个东西吧,,

参看资料:

one:https://www.cnblogs.com/murmured/p/5004082.html

two:https://blog.csdn.net/consciousman/article/details/53812818

three:https://blog.csdn.net/my_sunshine26/article/details/72849441


解决问题:

       给定M个一元不等式,以及N个变量X1-Xn,【M个不等式即为M个约束条件】,求一组X1-Xn的解。这个解呢,可以有很多个,可能只有1个,所以会衍生出3类问题:1》求任意两个变量差的最大值 ;2》求任意两个变量差的最小值 ;3》求有没有一组解能满足所有的约束条件;【三类问题随命题人心情出现,可能单独出现,可能成对出现】

引例:

       给定n个变量和m个不等式,每个不等式的形式为 x[i] - x[j] <= a[k] (0 <= i, j < n, 0 <= k < m,a[k]已知),求 x[i] - x[j] 的最大值。当n = 4,m = 5,给出如下图所示的不等式组,求x3 - x0的最大值。

解题思路:

       1》我们可以尝试把几个不等式组合得到最后我们要求的式子,于是这些式子里最小的那个就是答案。
            比如,在这个例子中:
                由 (3) 得到:x3 - x0<=4;
                由 (1) (4) (5) 得到: x3 - x0<=5;
                由 (2) (5) 得到:x3 - x0<=3;
                要同时满足这三个式子,则最后结果就是这里面最小的值:3 。【因为要同时满足所有的式子!所以最大的取值即为所有式子集合的最小值,领会精神】。
         2》在这个过程中,有没有有点像最短路算法?

             神仙结论:求解差分约束系统,都可以转化成图论的单源最短路径(或最长路径)问题。

             观察上面例子中的不等式,都是 x[ i ] - x[ j ] <= a[ k ],进行移项,转化成为 x[ i ] <= x[ j ] + a[ k ] 的形式,我们令 a[ k ] = w(j, i),dis[ i ]=x[ i ],并使i=v,j=u,那么原始就变为:dis[ u ]+w( u , v ) >= dis[ v ],于是可以联想到最短路模型中的一部分代码:

if(dis[u]+w(u,v)<=dis[v]){
    dis[v]=dis[u]+w(u,v);
}

             这不正与松弛操作相似吗?

         3》但是好像不等号方向刚好相反?这并不矛盾:上面的代码要实现的是:使dis[ u ]+w( u , v ) > dis[ v ];而对于不等式,我们进行建边的操作:对于每个不等式 x[i] - x[j] <= a[k],对结点 j 和 i 建立一条 j -> i的有向边,边权为a[k],求x[n-1] - x[0] 的最大值就是求 0 到n-1的最短路,两者刚好吻合所以求解差分约束问题就转化为了最短路问题【虽然我也不太明白为毛如此巧妙】。

算法思路:

        由于在求解最短路时会出现存在负环或者终点根本不可达的情况,在求解差分约束问题时同样存在:

        1》存在负环:如果路径中出现负环,就表示最短路可以无限小,即不存在最短路,那么在不等式上的表现即X[n-1] - X[0] <= T中的T无限小,得出的结论就是 X[n-1] - X[0] 的最大值不存在【联想:满足所有不等式,有一个满足不了的,就需要尽力去满足,有一个式子小于负无穷,你说人家怎么满足这个条件?】。在SPFA实现过程中体现为某一点的入队次数大于节点数。

        2》终点不可达:这种情况表明 X[n-1] 和 X[0] 之间没有约束关系,X[n-1] - X[0]的最大值无限大,即X[n-1]和X[0]的取值有无限多种。在代码实现过程中体现为dis[n-1]=INF。

        解法如下:

       1》根据条件把题意通过变量组表达出来得到不等式组,注意要发掘出隐含的不等式,比如说前后两个变量之间隐含的不等式关系。

        2》进行建图:

              首先根据题目的要求进行不等式组的标准化。

              (1)、如果要求取最小值,那么求出最长路,那么将不等式全部化成xi – xj >= k的形式,这样建立j->i的边,权值为k的边,如果不等式组中有xi – xj > k,因为一般题目都是对整形变量的约束,化为xi – xj >= k+1即可,如果xi – xj = k呢,那么可以变为如下两个:xi – xj >= k, xi – xj <= k,进一步变为xj – xi >= -k,建立两条边即可。

              (2)、如果求取的是最大值,那么求取最短路,将不等式全部化成xi – xj <= k的形式, 这样建立j->i的边,权值为k的边,如果像上面的两种情况,那么同样地标准化就行了。

              (3)、如果要判断差分约束系统是否存在解,一般都是判断环,选择求最短路或者最长路求解都行,只是不等式标准化时候不同,判环地话,用spfa即可,n个点中如果同一个点入队超过n次,那么即存在环

              值得注意的一点是:建立的图可能不联通,我们只需要加入一个超级源点,比如说求取最长路时图不联通的话,我们只需要加入一个点S,对其他的每个点建立一条权值为0的边图就联通了,然后从S点开始进行spfa判环。最短路类似。

          3》建好图之后直接spfa或bellman-ford求解,不能用dijstra算法,因为一般存在负边,注意初始化的问题。       

代码实现:

       这应该也算是最短路算法的应用了,代码是要根据题目的形式去变换的,我还木有做题,,先把大佬的博客mark住!

       http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html

猜你喜欢

转载自blog.csdn.net/sodacoco/article/details/84206158