下面是差分约束系统的详细介绍,以及解决方法~ 摘抄自 xuezhongfenfei(他好像也是转的....)
差分约束系统
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}肯定也是一组解,因为任何两个数同时加一个数之后,它们的差是不变的,那么这个差分约束系统中的所有不等式都不会被破坏。
d(v) <= d(u) + w(u, v)
X1 - X0 <= 0
X2 - X0 <= 0
X3 - X0 <= 0
X4 - X0 <= 0
X5 - X0 <= 0
不等式组(2)
图1
X0 = 0
d(v) >= d(u) + w(u, v)
也就是d(v) - d(u) >= w(u, v)
最近几天系统得学习了一些差分约束系统的原理,特此记录如下:
所谓差分约束系统,是指一组不定方程(A,x,T,b),其中A的每行有一个1,一个-1,其余为0,x为解向量,T为<=或>=组成的向量,b为约束矢量。具体来说,就是每行都具有 xi-xj >=|<= bi 的形式。约束的目标是使得目标函数xt-xs最大或最小。
这是典型的线性规划的个案,但是也可以转化为图论来做,利用最短路(或最长路)方法可以实现高效的解决方案。
SPFA的介绍:
http://blog.csdn.net/u013382399/article/details/44227003
这样最后再附上自己的代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> using namespace std; const int maxn = 110; const int INF = 0x3f3f3f3f; struct Edge{ int u,v,w,next; }edge[maxn*maxn]; int d[maxn],in[maxn],next[maxn]; bool vis[maxn]; int tot; int n,m; queue<int> q; void addEdge(int u,int v,int w){ edge[tot].u = u; edge[tot].v = v; edge[tot].w = w; edge[tot].next = next[u]; next[u] = tot++; } bool spfa(int size){ int u,v; while(!q.empty()) q.pop(); memset(in,0,sizeof(in)); memset(vis,0,sizeof(vis)); fill(d,d+size,INF); d[n+1] = 0;vis[n+1] = true;in[n+1] = 1; q.push(n+1); while(!q.empty()){ u = q.front();vis[u] = false; q.pop(); for(int i = next[u]; i != -1; i = edge[i].next){ v = edge[i].v; if(d[u] + edge[i].w < d[v]){ d[v] = d[u] + edge[i].w; if(!vis[v]){ vis[v] = true; in[v] ++; if(in[v] > size) return false; q.push(v); } } } } return true; } int main(){ int si,ni,ki; char oi[5]; while(scanf("%d",&n)){ if(n == 0) break; scanf("%d",&m); memset(next,-1,sizeof(next)); tot = 0; ///自己创造一个超级原点,建立与其他点链接的边(使其与其他点相连接) ///因为SPFA没有办法处理不连通的图 for(int i = 0; i <= n; i++){ addEdge(n+1,i,0);///我让点n+1作为一个超级源点,其余各节点的边权是0 } for(int i = 1; i <= m; i++){ scanf("%d%d%s%d",&si,&ni,oi,&ki); if(oi[0] == 'g') addEdge(si+ni,si-1,-(ki+1)); if(oi[0] == 'l') addEdge(si-1,si+ni,ki-1); } if (spfa(n + 2)) printf("lamentable kingdom\n");///总共有n+2个点 else printf("successful conspiracy\n"); } return 0; }
UVa 515 - King (差分约束系统 + SPFA求带负权最短路)
原文:http://blog.csdn.net/u013382399/article/details/44226011