差分约束系统

有不等式
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 }

 

posted @ 2015-05-16 09:42  sweat123  阅读(126)  评论(0编辑  收藏  举报