ZOJ 2770火烧连营——差分约束

偶尔做了一下差分约束。

题目大意:给出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 }
View Code

 

posted on 2016-12-22 14:58  gryzy  阅读(169)  评论(0编辑  收藏  举报

导航