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 }