首页 > 代码库 > 差分约束

差分约束

 

很好的讲解:http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html

 

差分约束:

一:求最大值,转换成求最短路。

给定不等式 A-B<=C;

步骤如下:

既然是求最短路,肯定要用到过程中最重要的【松弛操作】,即

if(dis[v]>dis[u]+w)   dis[v]=dis[u]+w;

这一步的目的是尽量使dis[v]<=dis[u]+w;

由此我们可把上面的不等式转化成类似的形式,即A<=B+C;(注意此处C可能是负值)

建立一条B到A边权为C的路,然后进行最短路即可。

二:求最小值,转换成求最长路。

基本和第一种相同。

不过是将不等式装换成B>=A-C;(再说一次C是带符号运算的!)

为了松弛操作时 if(dis[B]<dis[A]-C) dis[B]=dis[A]-C; 

 

上面都是最简单的线性约束的情况。。复杂一些的还不是很理解,等学好了再补。

Layout

 POJ - 3169

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=1010;
 6 const int maxe=20010;
 7 const int inf=0x3f3f3f3f;
 8 int n,m,c;
 9 int u,v,w;
10 struct edge
11 {
12     int v,w,nex;
13 }e[maxe];
14 int head[maxn],ins[maxn],sta[maxn],dis[maxn];
15 int cnt;
16 
17 void add(int u,int v,int w)
18 {
19     e[cnt].v=v;
20     e[cnt].w=w;
21     e[cnt].nex=head[u];
22     head[u]=cnt++;
23 }
24 
25 int spfa(int s)
26 {
27     for(int i=1;i<=n;i++)
28     {
29         dis[i]=inf;
30         ins[i]=0;
31     }
32     dis[s]=0;
33     ins[s]=1;
34     int top=0;
35     sta[top++]=s;
36     while(top)
37     {
38         int u=sta[--top];
39         for(int i=head[u];i!=-1;i=e[i].nex)
40         {
41             int v=e[i].v;
42             int w=e[i].w;
43             if(ins[v]==n) return -1;  //入队>=n次;说明存在负环
44             if(dis[v]>dis[u]+w)
45             {
46                 dis[v]=dis[u]+w;
47                 ins[v]++;
48                 sta[top++]=v;
49             }
50         }
51     }
52     if(dis[n]==inf) return -2;   //说明不可达
53     else return dis[n];
54 }
55 
56 int main()
57 {
58     while(scanf("%d%d%d",&n,&m,&c)!=EOF)
59     {
60         memset(head,-1,sizeof head);
61         cnt=0;
62         for(int i=0;i<m;i++)
63         {
64             scanf("%d%d%d",&u,&v,&w);  //d[v]-d[u]<=w  ->   d[v]<=d[u]+w  ->   if:  d[v]>d[u]+w
65             if(u>v) swap(u,v);
66             add(u,v,w);
67         }
68         for(int i=0;i<c;i++)
69         {
70             scanf("%d%d%d",&u,&v,&w);   //  d[v]-d[u]>=w  ->  d[u]<=d[v]-w  ->  if: d[u]>d[v]-w
71             if(u>v) swap(u,v);
72             add(v,u,-w);
73 
74         }
75         printf("%d\n",spfa(1));
76 
77 
78     }
79     return 0;
80 }
View Code

 

Candies

 POJ - 3159

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<stack>
 4 using namespace std;
 5 const int maxn=30010;
 6 const int maxe=150010;
 7 const int maxx=0x3f3f3f3f;
 8 int dis[maxn];
 9 int head[maxn];
10 int ins[maxn];
11 int cnt=0;
12 
13 int n,m;
14 int u,v,w;
15 
16 stack<int> sta;
17 struct edge
18 {
19     int v,w,nex;
20 }e[maxe];
21 
22 void add(int u,int v,int w)
23 {
24     e[cnt].v=v;
25     e[cnt].w=w;
26     e[cnt].nex=head[u];
27     head[u]=cnt++;
28 }
29 
30 int spfa(int s)
31 {
32     for(int i=0;i<=n;i++)
33     {
34         dis[i]=maxx;
35         ins[i]=0;
36     }
37     dis[1]=0;
38     ins[1]=1;
39     sta.push(1);
40     while(!sta.empty())
41     {
42         int u=sta.top();
43         sta.pop();
44         ins[u]=0;  //
45         for(int i=head[u];i!=-1;i=e[i].nex)
46         {
47             int v=e[i].v,w=e[i].w;
48             if(dis[v]>dis[u]+w)
49             {
50                 dis[v]=dis[u]+w;
51                 if(!ins[v])
52                 {
53                     ins[v]=1;
54                     sta.push(v);
55                 }
56             }
57         }
58     }
59     return dis[n];
60 }
61 int main()
62 {
63     while(scanf("%d%d",&n,&m)!=EOF)
64     {
65         cnt=0;
66         memset(head,-1,sizeof(head));
67         for(int i=0;i<m;i++)
68         {
69             scanf("%d%d%d",&u,&v,&w);
70             add(u,v,w);
71         }
72         printf("%d\n",spfa(1));
73     }
74 }
View Code

 

 

差分约束