差分约束系统学习笔记

     如果一个系统由n个变量和m个不等式组成,形如 Xj-Xi<=b*k(i,j属于[1,n],k属于[1,m] ), 这样的系统称之为差分约束系统。差分约束系统通常用于求关于一组变量的不等式组。

   求解差分约束系统可以转化为图论中单源最短路问题。

  Xj-Xi<=k  ==>   d[v]-d[u]<=w[u,v]   ( 这里是我们要根据约束条件求的结果,尽量往它靠近) ==>   所以转化为图论求解 ,也就是if(d[v]-d[u] >w[u,v]) 那么  d[v]-d[u]<=w[u,v] 。  路径距离初始化 dis[i]=INF

  Xj-Xi>=k  ==>   d[v]-d[u]>=w[u,v]   ( 这里是我们要根据约束条件求的结果,尽量往它靠近) ==>   所以转化为图论求解 ,也就是if(d[v]-d[u] <w[u,v]) 那么  d[v]-d[u]>=w[u,v]  。  路径距离初始化 dis[i]=-INF

  再增加一个源点s,源点到所有定点的距离为0( 添加源点的实质意义为默认另外一系列的不等式组Xi-Xo<=0),再对源点利用spfa算法。

 

  注意几个问题:

  1、当0没有被利用的时候,0作为超级源点。当0已经被利用了,将n+1(未被利用)置为超级源点。

  2、对于Xj-Xi=k 可以转换为 Xj-Xi<=k Xj-Xi>=k来处理。

  3、若要判断图中是否出现负环,可以利用深度优先搜索。以前利用spfa是这样的(head->****->tail),当head和tail之间所有点都遍历完了才轮得上tail这个点,这样的话我们无法判断图中有没有负环,我们可以这样改变一样遍历顺序,head->tail->***->head。 当深度优先搜索过程中下次再次遇见head(也就是head节点依然在标记栈中)时,则可判断图中含有负环,否则没有。

  4、当图连通时,只需要对源点spfa一次;当图不连通时,对每个定点spfa一次。

  5、对于  Xj-Xi<k or  Xj-Xi>k  , 差分约束系统只针对>= or <=, 所以我们还要进行巧妙转换编程大于等于小于等于。

 

poj 1201   ///spfa循环队列

View Code
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <vector>

 5 #include <algorithm>

 6 using namespace std;

 7 

 8 const int maxn=500005;

 9 const int oo=0x3fffffff;

10 int dis[maxn], inque[maxn], instack[maxn],que[maxn];

11 int n, s, t;

12 

13 struct Node

14 {

15     int v, val;

16     Node (int v_, int val_)

17     {

18         v=v_, val=val_;

19     }

20 };

21 vector<Node>vt[maxn];

22 

23 void spfa()

24 {

25     int l=0, h=0;

26     for(int i=s; i<=t; i++)

27         dis[i]=-oo, inque[i]=0;

28     que[l++]=s;

29     inque[s]=1;

30     dis[s]=0;

31     while(h<l)

32     {

33         int u=que[h++];

34         inque[u]=0;

35         if(h==maxn) h=0;

36         for(int i=0; i<vt[u].size(); i++)

37         {

38             int v=vt[u][i].v, val=vt[u][i].val;

39             if(dis[v]<dis[u]+val)

40             {

41                 dis[v]=dis[u]+val;

42                 if(!inque[v])

43                 {

44                     inque[v]=1;

45                     que[l++]=v;

46                     if(l==maxn) l=0;

47                 }

48             }

49         }

50     }

51 }

52 

53 int main()

54 {

55     while(cin >> n)

56     {

57         for(int i=0; i<maxn; i++)

58             vt[i].clear();

59         t=-1, s=oo;

60         for(int i=0; i<n; i++)

61         {

62             int u, v, val;

63             scanf("%d%d%d",&u,&v,&val);

64             s=min(s,u-1);

65             t=max(t,v);

66             vt[u-1].push_back(Node(v,val));

67         }

68         for(int i=s; i<=t; i++)

69         {

70             vt[i].push_back(Node(i+1,0));

71             vt[i+1].push_back(Node(i,-1));

72             vt[0].push_back(Node(i,0));

73         }

74         spfa();

75         printf("%d\n",dis[t]-dis[s]);

76     }

77     return 0;

78 }

 

poj 2983  ///spfa+深度优先搜索判断负环

View Code
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <vector>

 5 #include <algorithm>

 6 using namespace std;

 7 

 8 const int maxn=10005;

 9 const int oo=0x3fffffff;

10 int dis[maxn], inque[maxn], instack[maxn], que[maxn];

11 int n, m, s, t;

12 

13 struct Node

14 {

15     int v, val;

16     Node (int v_, int val_)

17     {

18         v=v_, val=val_;

19     }

20 };

21 vector<Node>vt[maxn];

22 

23 bool spfa(int u)   

24 {

25     instack[u]=1;

26     for(int i=0; i<vt[u].size(); i++)

27     {

28         int v=vt[u][i].v, val=vt[u][i].val;

29         if(dis[v]>dis[u]+val)

30         {

31             dis[v]=dis[u]+val;

32             if(!instack[v])

33             {

34                 if(spfa(v))

35                     return true;

36             }

37             else

38                 return true;

39         }

40     }

41     instack[u]=0;

42     return false;

43 }

44 

45 int main()

46 {

47     while(cin >> n >> m)

48     {

49         for(int i=0; i<=n; i++)

50         {

51             dis[i]=oo;

52             vt[i].clear();

53             instack[i]=0;

54         }

55         for(int i=0; i<m; i++)

56         {

57             char ch[2];

58             int u, v, val;

59             scanf("%s",ch);

60             if(ch[0]=='P')

61             {

62                 scanf("%d%d%d",&u,&v,&val);

63                 vt[u].push_back(Node(v,val));

64                 vt[v].push_back(Node(u,-val));

65             }

66             else

67             {

68                 scanf("%d%d",&u,&v);

69                 vt[v].push_back(Node(u,-1));

70             }

71         }

72         for(int i=0; i<=n; i++)

73             vt[0].push_back(Node(i,0));

74         dis[0]=0;

75         bool ok=spfa(0);

76         if(ok)

77             puts("Unreliable");

78         else puts("Reliable");

79     }

80     return 0;

81 }

 

hdu 3666

View Code
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <vector>

 5 #include <cmath>

 6 #include <algorithm>

 7 using namespace std;

 8 

 9 const int maxn=1024;

10 const double oo=0x3fffffff;

11 double dis[maxn];

12 int  instack[maxn];

13 int n, m;

14 double  L, U;

15 

16 struct Node

17 {

18     int v;

19     double val;

20     Node(int v_, double val_)

21     {

22         v=v_, val=val_;

23     }

24 };

25 vector<Node>vt[maxn];

26 

27 bool spfa(int u)

28 {

29     instack[u]=1;

30     for(int i=0; i<vt[u].size(); i++)

31     {

32         int v=vt[u][i].v;

33         double  val=vt[u][i].val;

34         if(dis[v]<dis[u]+val)

35         {

36             dis[v]=dis[u]+val;

37             if(!instack[v])

38             {

39                 if(spfa(v))

40                     return true;

41             }

42             else

43                 return true;

44         }

45     }

46     instack[u]=0;

47     return false;

48 }

49 

50 bool judge()

51 {

52     for(int i=1; i<=n+m; i++)

53     {

54         fill(dis,dis+n+m+1,-oo);

55         fill(instack,instack+n+m+1,0);

56         if(spfa(i))

57             return true;

58     }

59     return false;

60 }

61 

62 int main()

63 {

64     while(cin >> n >> m >> L >> U)

65     {

66         for(int i=0; i<=n+m+1; i++)

67             vt[i].clear();

68         for(int i=1; i<=n; i++)

69             for(int j=1; j<=m; j++)

70             {

71                 double val;

72                 scanf("%lf",&val);

73                 vt[j+n].push_back(Node(i,log(L)-log(val)));

74                 vt[i].push_back(Node(j+n,-(log(U)-log(val))));

75             }

76         bool ok=judge();

77         if(ok)

78             puts("NO");

79         else puts("YES");

80     }

81     return 0;

82 }

 

poj 1364

View Code
#include <iostream>

#include <cstdio>

#include <cstring>

#include <vector>

#include <cmath>

#include <algorithm>

using namespace std;



const int maxn=10024;

const double oo=0x3fffffff;

double dis[maxn];

int  instack[maxn];

int n, m, t;



struct Node

{

    int v;

    double val;

    Node(int v_, double val_)

    {

        v=v_, val=val_;

    }

};

vector<Node>vt[maxn];



bool spfa(int u)

{

    instack[u]=1;

    for(int i=0; i<vt[u].size(); i++)

    {

        int v=vt[u][i].v;

        double  val=vt[u][i].val;

        if(dis[v]<dis[u]+val)

        {

            dis[v]=dis[u]+val;

            if(!instack[v])

            {

                if(spfa(v))

                    return true;

            }

            else

                return true;

        }

    }

    instack[u]=0;

    return false;

}



int main()

{

    int u, v, val;

    char ch[5];

    while(cin >> n, n)

    {

        cin >> m;

        for(int i=0; i<maxn; i++)

            vt[i].clear();

        t=-1;

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

        {

            scanf("%d%d%s%d",&u,&v,ch,&val);

            t=max(t,u+v);

            if(ch[0]=='g')

            {

                vt[u-1].push_back(Node(u+v,val+1));

            }

            else

            {

                vt[u+v].push_back(Node(u-1,-val+1));

            }

        }

        for(int i=0; i<=t; i++)   ///注意超级源点的建立

            vt[t+1].push_back(Node(i,0));

        for(int i=0; i<=t; i++)

            dis[i]=-oo, instack[i]=0;

        dis[t+1]=0;

        bool ok=spfa(t+1);

        if(ok)

            puts("successful conspiracy");

        else puts("lamentable kingdom");

    }

    return 0;

}

 

 

 

你可能感兴趣的:(学习笔记)