poj 3169 差分约束
差分约束的是满足多组形如xi-yj<=bk{i,j<n k<m}不等式极值问题,可以转化为单源最短路来求。
在最短路中 d[v]<=d[u]+w(u,v) 可以看出跟上面的不等式很像
通常有两种一种是求满足所有不等式的最大值,还有是最小值。
分析:
题目给出了两种不等式 d[u]+dl >=d[v] d[u]+dd<=d[v] 要求的是最大值,也就是最短路
对于d[u]+dl>=d[v] 建边(u,vdl)
对于d[u]+dd<=d[v] 建边(v,u,-dd)
然后跑一边最短路就好了,注意是负权图
如果有负环则无解,有点最短距离未更新为多解,否则为S->e的最短距离
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <set> 5 #include <algorithm> 6 #include <map> 7 #include <queue> 8 #include<vector> 9 #define maxn 50010 10 #define maxm 100010 11 #define INF 0x3fffffff 12 using namespace std; 13 struct edge{ 14 int from,to,w; 15 edge(){} 16 edge(int _u,int _v,int _w){ 17 from=_u,to=_v,w=_w; 18 } 19 }; 20 edge G[maxm]; 21 int V,E; 22 void addedge(int u,int v,int w){ 23 G[E++]=edge(u,v,w); 24 } 25 int d[maxn]; 26 int n,m; 27 void bellman_ford(int s){ 28 V=n; 29 for(int i=0;i<V;++i)d[i]=INF; 30 d[s]=0; 31 while(1){ 32 bool flag =false; 33 for(int i=0;i<E;++i){ 34 edge e = G[i]; 35 if(d[e.from]!=INF&&d[e.to]>d[e.from]+e.w){ 36 d[e.to] = d[e.from]+e.w; 37 flag = true; 38 } 39 } 40 if(!flag)break; 41 } 42 } 43 bool HaveNagativeLoop(){ 44 memset(d,0,sizeof(d)); 45 for(int i=0;i<V;++i){ 46 for(int j=0;j<E;++j){ 47 edge e = G[j]; 48 if(d[e.to]>d[e.from]+e.w){ 49 d[e.to] = d[e.from]+e.w; 50 if(i==V-1)return true; 51 } 52 } 53 } 54 return false; 55 } 56 int ml,md; 57 int main (){ 58 while(scanf("%d%d%d",&n,&ml,&md)!=EOF){ 59 int u,v,w; 60 E=0; 61 V=n; 62 for(int i=0;i<n-1;++i){ 63 addedge(i+1,i,0); 64 } 65 for(int i=0;i<ml;++i){ 66 scanf("%d%d%d",&u,&v,&w); 67 addedge(u-1,v-1,w); 68 } 69 for(int i=0;i<md;++i){ 70 scanf("%d%d%d",&u,&v,&w); 71 addedge(v-1,u-1,-w); 72 } 73 if(HaveNagativeLoop()){printf("-1\n");continue;} 74 bellman_ford(0); 75 if(d[n-1]==INF)printf("%d\n",-2); 76 else printf("%d\n",d[n-1]); 77 } 78 }