差分约束系统

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

 2 #include<stdio.h>

 3 #include<string.h>

 4 #include<queue>

 5 using namespace std;

 6 #define INF 99999999

 7 struct node

 8 {

 9     int v;

10     int w;

11     int next;

12 }edge[150005];

13 int n,m,index,head[30005],dis[30005];

14 void add(int x,int y,int z)

15 {

16     int i,j;

17     edge[index].v=y;

18     edge[index].w=z;

19     edge[index].next=head[x];

20     head[x]=index++;

21 }

22 struct Node

23 {

24     int point,dist;

25     bool operator<(const Node x) const

26     {

27         return x.dist<dist;

28     }

29 };

30 

31 void dij(int s)

32 {

33     priority_queue<Node> q;

34     int vis[30005];

35     int i,j;

36     for(i=0;i<=n;i++)

37     {

38         dis[i]=INF;

39         vis[i]=0;

40     }

41     dis[s]=0;

42     Node cur;

43     cur.point=s;

44     cur.dist=0;

45     q.push(cur);

46     while(!q.empty())

47     {

48         Node tmp;

49         tmp=q.top();

50         q.pop();

51         int u=tmp.point;

52         if(vis[u])

53             continue;

54         vis[u]=1;

55         for(j=head[u];j!=-1;j=edge[j].next)

56         {

57             if(!vis[edge[j].v]&&dis[edge[j].v]>dis[u]+edge[j].w)

58             {

59                 dis[edge[j].v]=dis[u]+edge[j].w;

60                 cur.dist=dis[edge[j].v];

61                 cur.point=edge[j].v;

62                 q.push(cur);

63             }

64         }

65     }

66 }

67 

68 int main()

69 {

70     int i,j;

71     while(scanf("%d%d",&n,&m)!=EOF)

72     {

73         index=1;

74         memset(head,-1,sizeof(head));

75         for(i=0;i<m;i++)

76         {

77             int x,y,z;

78             scanf("%d%d%d",&x,&y,&z);

79             add(x,y,z);

80         }

81         dij(1);

82         printf("%d\n",dis[n]);

83     }

84 }
 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 }

 

你可能感兴趣的:(差分约束)