首页 > 代码库 > ZOJ 2770 Burn the Linked Camp 差分约束 (转)

ZOJ 2770 Burn the Linked Camp 差分约束 (转)

It is well known that, in the period of The Three Empires, Liu Bei, the emperor of the Shu Empire, was defeated by Lu Xun, a general of the Wu Empire. The defeat was due to Liu Bei‘s wrong decision that he divided his large troops into a number of camps, each of which had a group of armies, and located them in a line. This was the so-called "Linked Camps".

Let‘s go back to that time. Lu Xun had sent many scouts to obtain the information about his enemy. From his scouts, he knew that Liu Bei had divided his troops into n camps, all of which located in a line, labeled by 1..n from left to right. The ith camp had a maximum capacity of Ci soldiers. Furthermore, by observing the activities Liu Bei‘s troops had been doing those days, Lu Xun could estimate the least total number of soldiers that were lived in from the ith to the jth camp. Finally, Lu Xun must estimate at least how many soldiers did Liu Bei had, so that he could decide how many troops he should send to burn Liu Bei‘s Linked Camps.

Input:

There are multiple test cases! On the first line of each test case, there are two integers n (0<n<=1,000) and m (0<=m<=10,000). On the second line, there are n integers C1??Cn. Then m lines follow, each line has three integers i, j, k (0<i<=j<=n, 0<=k<2^31), meaning that the total number of soldiers from the ith camp to the jth camp is at least k.

Output:

For each test case, output one integer in a single line: the least number of all soldiers in Liu Bei‘s army from Lu Xun‘s observation. However, Lu Xun‘s estimations given in the input data may be very unprecise. If his estimations cannot be true, output "Bad Estimations" in a single line instead.

Sample Input:

3 2 1000 2000 1000 1 2 1100 2 3 1300 3 1 100 200 300 2 3 600 

Sample Output:

1300 Bad Estimations

题目大意:

大家都知道,三国时期,蜀国刘备被吴国大都督陆逊打败了。刘备失败的原因是因为刘备的错误决策。他把部队分成几十个大营,每个大营驻扎一队部队,又用树木编成栅栏,把大营连成一片,称为连营。
让我们回到那个时代。陆逊派了很多密探,获得了他的敌人-刘备的信息。通过密探,他知道刘备的部队已经分成几十个大营,这些大营连成一片(一字排开),这些大营从左到右用1...n编号。第i个大营最多能容纳Ci个士兵。而且通过观察刘备军队的动静,陆逊可以估计到从第i个大营到第j个大营至少有多少士兵。最后,陆逊必须估计出刘备最少有多少士兵,这样他才知道要派多少士兵去烧刘备的大营。
为陆逊估计出刘备军队至少有多少士兵。然而,陆逊的估计可能不是很精确,如果不能很精确地估计出来,输出"Bad Estimations"

 

对于样例数据:

数学模型为:设3个军营的人数分别为A1, A2, A3,容量为C1, C2, C3,前n个军营的总人数为Sn,则有:

1. 则根据第i个大营到第j个大营士兵总数至少有k个,得不等式组(1):
S2 – S0 >= 1100 等价于 S0 – S2 <= -1100
S3 – S1 >= 1300 等价于 S1 – S3 <= -1300

2. 又根据实际情况,第i个大营到第j个大营的士兵总数不超过这些兵营容量之和,设d[i]为前i个大营容量总和,得不等式组(2):
S2 – S0 <= d[2] – d[0] = 3000
S3 – S1 <= d[3] – d[1] = 3000

3. 每个兵营实际人数不超过容量,得不等式组(3)
A1 <= 1000 等价于 S1 – S0 <= 1000
A2 <= 2000 等价于 S2 – S1 <= 2000
A3 <= 1000 等价于 S3 – S2 <= 1000

4. 另外由Ai>=0,又得到不等式组(4)
S0 – S1 <= 0
S1 – S2 <= 0
S2 – S3 <= 0
求A1+A2+A3的最小值(即S3 – S0的最小值)

构造好网络之后,最终要求什么?
要求S3 – S0的最小值,即要求不等式:
S3 – S0 >= M
中的M,转化成:
S0 – S3 <= -M
即求S3到S0的最短路径,长度为-M
求得-M为-1300,即M为1300

  1. #include <stdio.h>  
  2. #define INF 9999999  
  3. int n,m,dist[1010],c[1010],d[1010],ei;  
  4. struct eg  
  5. {  
  6.     int u,v,w;  
  7. }edges[23000];  
  8. void init()  
  9. {  
  10.     ei=0;  
  11.     int i;  
  12.     for(i=0;i<=n;i++)  
  13.         dist[i]=INF;  
  14.     d[0]=0;  
  15.     dist[n]=0;  
  16. }  
  17. bool bell()  
  18. {  
  19.     int i,k,t;  
  20.     for(i=0;i<n;i++)  
  21.     {  
  22.         for(k=0;k<ei;k++)  
  23.         {  
  24.             t=dist[edges[k].u]+edges[k].w;  
  25.             if(dist[edges[k].u]!=INF&&t<dist[edges[k].v])  
  26.                 dist[edges[k].v]=t;  
  27.         }  
  28.     }  
  29.     for(k=0;k<ei;k++)  
  30.     {  
  31.         if(dist[edges[k].u]!=INF&&dist[edges[k].u]+edges[k].w<dist[edges[k].v])  
  32.             return false;  
  33.     }  
  34.     return true;  
  35. }  
  36. int main()  
  37. {  
  38.     while(scanf("%d%d",&n,&m)!=EOF)  
  39.     {  
  40.         init();  
  41.         int i,u,v,w;  
  42.         for(i=1;i<=n;i++)  
  43.         {  
  44.             scanf("%d",&c[i]);  
  45.             edges[ei].u=i-1;  
  46.             edges[ei].v=i;  
  47.             edges[ei].w=c[i];  
  48.             ei++;  
  49.             edges[ei].u=i;  
  50.             edges[ei].v=i-1;  
  51.             edges[ei].w=0;  
  52.             ei++;  
  53.             d[i]=c[i]+d[i-1];  
  54.         }  
  55.         for(i=0;i<m;i++)  
  56.         {  
  57.             scanf("%d%d%d",&u,&v,&w);  
  58.             edges[ei].u=v;  
  59.             edges[ei].v=u-1;  
  60.             edges[ei].w=-w;  
  61.             ei++;  
  62.             edges[ei].u=u-1;  
  63.             edges[ei].v=v;  
  64.             edges[ei].w=d[v]-d[u-1];  
  65.             ei++;  
  66.         }  
  67.         if(!bell())  
  68.             printf("Bad Estimations\n");  
  69.         else printf("%d\n",-dist[0]);  
  70.     }  
  71.     return 0;  



ZOJ 2770 Burn the Linked Camp 差分约束 (转)