差分约束
Posted yijiull
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了差分约束相关的知识,希望对你有一定的参考价值。
很好的讲解: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
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 }
Candies
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 }
以上是关于差分约束的主要内容,如果未能解决你的问题,请参考以下文章