偶尔做了一下差分约束。
题目大意:给出n个军营,每个军营最多有ci个士兵,且[ai,bi]之间至少有ki个士兵,问最少有多少士兵。
————————————————————————————————————————————————---
差分约束:就是利用多个不等式来推导另一个不等式。
由于不等式a-b<=c和求最短路径时的三角形不等式相同,就变成了求最短路。
所有不等式化为a-b<=c的形式,则建造b到a的边,权为c。
求a到b的最短距离,则转化为b-a<=c,距离的值为c。
该题中:
Si表示从第一营到i营的人数,则有:
每个营的人数不少于0,Si-Si-1>=0,进而推出Si-1-Si<=0;
每个营的人数不大于Ci,从而推出Si-Si-1<=Ci;
第i营到第j营人数不少于k,从而推出Sj-Si-1>=k,进而推出Si-1-Sj<=-k
从以上三组不等式分别建边,组成图。
求的是所有应最少有多少人,即Sn-S0>=x,求的就是x.
从上式推出S0-Sn<=-x,所以从Sn求到S0的最短路,就是x的相反数。
————————————————————————————————————————————————————
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<queue> 7 using namespace std; 8 int n,m; 9 struct edge 10 { 11 int u,v,w,next; 12 }e[20010]; 13 int head[1010],js; 14 int dis[1010]; 15 int inqt[1010]; 16 bool inq[1010]; 17 queue<int>q; 18 void init() 19 { 20 memset(head,0,sizeof(head)); 21 js=0; 22 } 23 void readint(int &x) 24 { 25 char c=getchar(); 26 int f=1; 27 for(;c>'9'||c<'0';c=getchar())if(c=='-')f=-f; 28 x=0; 29 for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0'; 30 x*=f; 31 } 32 void addage(int u,int v,int w) 33 { 34 e[++js].u=u;e[js].v=v;e[js].w=w; 35 e[js].next=head[u];head[u]=js; 36 } 37 bool spfa() 38 { 39 memset(dis,0x7f,sizeof(dis)); 40 memset(inq,0,sizeof(inq)); 41 memset(inqt,0,sizeof(inqt)); 42 dis[n]=0; 43 inqt[n]=1; 44 q.push(n); 45 inq[n]=1; 46 while(!q.empty()) 47 { 48 int u=q.front(); 49 q.pop(); 50 inq[u]=0; 51 for(int i=head[u];i;i=e[i].next) 52 { 53 int v=e[i].v; 54 if(dis[v]>dis[u]+e[i].w) 55 { 56 dis[v]=dis[u]+e[i].w; 57 if(!inq[v]) 58 { 59 q.push(v); 60 inq[v]=1; 61 inqt[v]++; 62 if(inqt[v]>n)return 0; 63 } 64 } 65 } 66 } 67 return 1; 68 } 69 int main() 70 { 71 while(scanf("%d%d",&n,&m)==2) 72 { 73 init(); 74 for(int c,i=1;i<=n;i++) 75 { 76 readint(c); 77 addage(i-1,i,c); 78 addage(i,i-1,0); 79 } 80 for(int a,b,c,i=0;i<m;i++) 81 { 82 readint(a);readint(b);readint(c); 83 addage(b,a-1,-c); 84 } 85 if(spfa())printf("%d\n",-dis[0]); 86 else printf("Bad Estimations\n"); 87 } 88 return 0; 89 }