差分约束
很好的讲解: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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
Halum
UVA - 11478![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }