差分约束系统的图解法; 形式很特殊的一种线性规划问题; 可以转化为求带负边最短路问题;

#include <stdio.h> /*********************************/ * 差分系统的约束图 * 由于bellman算法只需要边的信息 * 所以只存边的相关信息就可以了 /*********************************/ const int MAXN = 10000; int u[MAXN],v[MAXN],w[MAXN]; int dist[MAXN]; int n,m; /*********************************/ * 解决差分约束型线性规划问题 * 形如: * x1-x2 <= b1 * x3-x1 <= b2 * 的线性规划问题,属于差分约束范畴 * 可以转化成图的最短路径问题 * 假如存在:x1-x2 <= b1 * 那么构图时就有一条<x2,x1>的有向边 * 权值为b1 * 由于权值b可能为负,所以使用bellman最短路算法 * 求得的每个顶点的最短路就是解: * x1,x2....xn * 如果bellman返回true,则有解 * 否则无解. * 求的得解整体+任意数d,仍然为解 * 因为(x1+d)-(x2+d) <= b1 * dist(v1)-dist(v2) <= b * dist(v1) <= dist(v2)+b * 这符合最短路松弛定理(三角形不等式) * 所以构图时,x2->x1的边,权值为b /*********************************/ bool bellMan() { for(int k=0;k<n;++k) { dist[k]=MAXN; } dist[0]=0; for(int i=1;i<=n-1;++i) //松弛n-1次 { for(int j=0;j<m;++j) { if(dist[v[j]]>dist[u[j]]+w[j]) { dist[v[j]]=dist[u[j]]+w[j]; } } } for(int k=0;k<m;++k) { if(dist[v[k]]>dist[u[k]]+w[k]) { return false; } } printf("("); for(int k=1;k<n-1;++k) { printf("x%d=%d,",k,dist[k]); } printf("xn=%d)/n",dist[n-1]); return true; } /* x1-x2 <=0 x1-x5 <=-1 x2-x5 <=1 x3-x1 <=5 x4-x1 <=4 x4-x3 <=-1 x5-x3 <=-3 x5-x4 <=-3 input: 5 8 2 1 0 5 1 -1 5 2 1 1 3 5 1 4 4 3 4 -1 3 5 -3 4 5 -3 */ int main() { scanf("%d%d",&n,&m); //n未知量数目,m为不等式数目 ++n; for(int i=0;i<m;++i) { scanf("%d%d%d",&u[i],&v[i],&w[i]); } //进一步构造差分约束图,添加v0到v1,v2....vn的边,权为0 for(int j=1;j<=n-1;++j) { u[m]=0; v[m]=j; w[m++]=0; } bellMan(); return 0; }

 

 

算法的原理是根据最短路的三角形不等式分析得到的,因为这组不等式恰好与三角形不等式吻合,所以这个规划问题就转化成了求最短路问题了.

 

这里只讲算法过程: 首先输入m条边, 这些边是根据不等式输入的 ,假设存在x1-x2<=b,那么转化成x1<=x2+b,就是三角形不等式了,可以转化成<x2,x1>这条有向边,其权值是b.

 

程序必须添加上vo到v1,v2,v3.........这些边,权值为0.

 

由于x1<=x2+b这种三角形不等式形式, 所以x1 与x2 自然而然的就对应到图中顶点的最短路径, 所以v1,v2...分别作为图中顶点, 只要求得x1(dist[v1]),x2(dist[v2]).........就是解了.

你可能感兴趣的:(算法,input,include,IM)