差分约束

 

很好的讲解: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

 

 

Halum

 UVA - 11478 
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int inf=0x3f3f3f3f;
  4 const int maxv=510;
  5 const int maxe=3000;
  6 #define CLR(m,a) memset(m,a,sizeof(m))
  7 
  8 struct Edge
  9 {
 10     int v,w,nex;
 11 }e[maxe];
 12 int head[maxv];
 13 int cnt=0;
 14 void init()
 15 {
 16     CLR(head,-1);
 17     cnt=0;
 18 }
 19 void add(int u,int v,int w)
 20 {
 21     e[cnt].v=v;
 22     e[cnt].w=w;
 23     e[cnt].nex=head[u];
 24     head[u]=cnt++;
 25 }
 26 int n,m;
 27 
 28 int inq[maxv],dis[maxv],deg[maxv];
 29 int bellman()
 30 {
 31     queue<int> q;
 32     CLR(dis,inf);
 33     CLR(inq,0);
 34     CLR(deg,0);
 35     for(int i=0;i<n;i++){
 36         q.push(i); dis[i]=0; inq[i]=1; deg[i]=1;
 37     }
 38     while(!q.empty()){
 39         int u=q.front();
 40         q.pop();
 41         inq[u]=0;
 42         for(int i=head[u];~i;i=e[i].nex){
 43             int v=e[i].v;
 44             if(dis[v]>dis[u]+e[i].w){
 45                 dis[v]=dis[u]+e[i].w;
 46                 if(!inq[v]){
 47                     inq[v]=1;
 48                     q.push(v);
 49                     if(++deg[v]>=n) return 1;
 50                 }
 51             }
 52         }
 53     }
 54     return 0;
 55 }
 56 int check(int x)
 57 {
 58     int ok=1;
 59     for(int i=0;i<n;i++){
 60         for(int j=head[i];~j;j=e[j].nex){
 61             e[j].w-=x;
 62         }
 63     }
 64     if(bellman()) ok=0;
 65     for(int i=0;i<n;i++){
 66         for(int j=head[i];~j;j=e[j].nex){
 67             e[j].w+=x;
 68         }
 69     }
 70     return ok;
 71 }
 72 int main()
 73 {
 74     while(scanf("%d%d",&n,&m)!=EOF){
 75         init();
 76         int u,v,w;
 77         int maxw=0;
 78         for(int i=0;i<m;i++){
 79             scanf("%d%d%d",&u,&v,&w);
 80             u--;v--;
 81             add(u,v,w);
 82             maxw=max(maxw,w);
 83         }
 84         if(check(maxw+1)){
 85             puts("Infinite");
 86             continue;
 87         }
 88         if(!check(1)){
 89             puts("No Solution");
 90             continue;
 91         }
 92         int L=2,R=maxw;
 93         while(L<=R){
 94             int m=L+(R-L)/2;
 95             if(check(m)) L=m+1;
 96             else R=m-1;
 97         }
 98         printf("%d\n",R);
 99     }
100 }
View Code

 

posted @ 2017-07-26 23:59  yijiull  阅读(119)  评论(0编辑  收藏  举报