zoj 2770 差分约束

  1 /*
  2 题意:给出N个营地,每个营地最多可容纳Ci人,给出m个三元组i,j,k分别表示当前营地从i到j至少有
  3 k个人,问N个营地总共至少有多少人
  4 
  5 题解:差分约束(SPFA)
  6 题目中给出的很多条件都是约束的条件,例如最多有Ci个人,最少有k个人,问的问题也同样是最少多
  7 少人,当所有给出的都是限制条件,然后自然会写出一些不等式,然后就可以联想到用差分系统来做
  8 (马后炮的想法,当时想的时候也是没有考虑用差分系统),然后就是从题目中找出不等式:
  9 设x[i] 为第i个营的人数,s[i] = x[1] + x[2] + … + x[i], s[0] = 0
 10    Ci 有: 0 <= s[i] – s[i-1] <= Ci
 11    i, j, k有: s[j] – s[i-1] >= k
 12    还有: s[i] >= 0 (1 <= i <= n) , 即 s[i] – s[0] >= 0
 13 因为题目要求的是最小值,因此需要转换为求最长路,不等式要全变成s[i]-s[j] >= t的形式,然后
 14 建图求最长路即可(为什么是求最长路而不是最短路,其实可以通过s[i]-s[j] >= t思考,因为要求
 15 的是一个最小值,其中的s[i]-s[j]>=t表示至少大于某个给出值,这样在求的时候才会有一个极限,
 16 否则以s[i]-[j]<=t的形式去求,则值可以变成负数无限的小,从而无法求出答案,而首先给出一个限
 17 定的最小值的形式,这样就能求出最小值,至于求最长还是求最短路就从不等式的形式去判断,这个
 18 想法纯属YY,没有科学证明)
 19 */
 20 #include <cstdio>
 21 #include <cstring>
 22 #include <iostream>
 23 #include <queue>
 24 
 25 #define clr(a,b) (memset(a,b,sizeof(a)))
 26 #define cpy(a,b) (memcpy(a,b,sizeof(b)))
 27 using namespace std;
 28 
 29 const int NV = 1005;
 30 const int NE = 15005;
 31 const int INF = 0x7f7f7f7f;
 32 
 33 int n;
 34 int dis[NV],head[NV],insum[NV];
 35 bool in[NV];
 36 int SZ;
 37 struct edge {
 38     int v,d,next;
 39 }E[NE];
 40 
 41 inline void init(int nn) {
 42     n = nn;
 43     SZ = 0;
 44     clr(head,-1);
 45     clr(insum,0);
 46     clr(in,false);
 47     clr(dis,0x7f);
 48 }
 49 inline bool relax(int u,int v,int w) {
 50     if(dis[v] == INF || dis[u] + w > dis[v]) {//大于,求最长路
 51         dis[v] = dis[u] + w;
 52         return true;
 53     }
 54     return false;
 55 }
 56 inline bool spfa(int start) {
 57     int i;
 58     queue<int>q;
 59     dis[start] = 0;
 60     q.push(start);
 61     while(!q.empty()) {
 62         int u = q.front();
 63         q.pop();
 64         in[u] = false;
 65         for(i = head[u];i != -1;i = E[i].next) {
 66             int v = E[i].v;
 67             if(relax(u,v,E[i].d) && !in[v]) {
 68                 in[v] = true;
 69                 insum[v]++;
 70                 if (insum[v] >= n)
 71                     return false;
 72                 q.push(v);
 73             }
 74         }
 75     }
 76     return true;
 77 }
 78 inline void insert(int from,int to,int dis) {
 79     E[SZ].v = to;
 80     E[SZ].d = dis;
 81     E[SZ].next = head[from];
 82     head[from] = SZ ++;
 83 }
 84 int main(void)
 85 {
 86     int m;
 87     while (~scanf("%d%d",&n,&m))
 88     {
 89         init(n);
 90         for(int i=1; i<=n; i++)
 91         {
 92             int c;
 93             scanf("%d",&c);
 94             insert(i-1,i,0);
 95             insert(i,i-1,-c);
 96             insert(0,i,0);
 97         }
 98         while (m--)
 99         {
100             int i,j,k;
101             scanf("%d%d%d",&i,&j,&k);
102             insert(i-1,j,k);
103         }
104         if (spfa(0))
105             printf("%d\n",dis[n]);
106         else
107             printf("Bad Estimations\n");
108     }
109     return 0;
110 }

 

posted @ 2014-04-06 21:16  辛力啤  阅读(198)  评论(0编辑  收藏  举报