差分约束系统
有不等式
x1-x2<=0;
x1-x2<=-1;
x2-x5<=1;
x3-x1<=5;
x4-x1<=4;
x4-x3<=-1;
x5-x3<=-3;
x5-x4<=-3;
在每个不等式都是两个未知数的差小于等于某个常数(或大于等于),这样的不等式组就称为差分约束系统;
这个不等式组要么无解,要么有无穷多的解;
差分约束系统求解要利用最短路径的三角不等式:d(v)<=d(u)+edge[u][v];d(u),d(v)表示源点到u,v点的最短路径长度;
构造方法:
(1)每个不等式中的每个未知数xi对应图中的一个顶点vi;
(2)把所有的不等式化成图中的一条边。对于不等式xi-xj<=c,把他化成三角不等式:xi<=xj+c,就有边<vj,vi>的权值等于c(edge[vj[vi]=c);
设一个起点,最后在这张图上求一次单源最短路径即可。用Bellman-ford算法比较好,方程组无解时也就是存在负环;起点到各点的最短路径即为该不等式组的一组解;
1 //poj3169 2 /* 3 网上很多代码都是错的,但是竟然都过了, 4 所以差不多网上代码出于同一人之手(^v^) 5 */ 6 #include<stdio.h> 7 #include<string.h> 8 #define INF 99999999 9 struct node 10 { 11 int u; 12 int v; 13 int w; 14 }edge[22003]; 15 int index,n,ml,md,dis[1003]; 16 void add(int x,int y,int z) 17 { 18 int i,j; 19 edge[index].u=x; 20 edge[index].v=y; 21 edge[index].w=z; 22 index++; 23 } 24 int bell() 25 { 26 int i,j; 27 for(i=1;i<=n;i++) 28 dis[i]=INF; 29 dis[1]=0; 30 for(i=1;i<n;i++) 31 { 32 for(j=1;j<index;j++) 33 { 34 int u=edge[j].u; 35 int v=edge[j].v; 36 int w=edge[j].w; 37 if(dis[v]>dis[u]+w) 38 { 39 dis[v]=dis[u]+w; 40 } 41 } 42 } 43 for(i=1;i<index;i++) 44 { 45 int u=edge[i].u; 46 int v=edge[i].v; 47 int w=edge[i].w; 48 if(dis[v]>dis[u]+w&&dis[u]!=INF) 49 return 0; 50 } 51 return 1; 52 } 53 int main() 54 { 55 int i,j; 56 while(scanf("%d%d%d",&n,&ml,&md)!=EOF) 57 { 58 index=1; 59 int x,y,z; 60 for(i=1;i<n;i++) 61 { 62 add(i+1,i,0); 63 } 64 for(i=1;i<=ml;i++) 65 { 66 scanf("%d%d%d",&x,&y,&z); 67 add(x,y,z); 68 } 69 for(i=1;i<=md;i++) 70 { 71 scanf("%d%d%d",&x,&y,&z); 72 add(y,x,-z); 73 } 74 int ans=bell(); 75 if(ans==0) 76 printf("-1\n"); 77 else if(dis[n]==INF) 78 { 79 printf("-2\n"); 80 } 81 else printf("%d\n",dis[n]); 82 83 } 84 }