题意:陆逊已知刘备的每个大营最多能容纳Ci个士兵,并且可以估计到第i个大营到第j个大营至少有多少士兵,求刘备最少有多少个士兵。
分析:根据给出的数据我们可以得到一系列不等式组,考虑采用差分约束系统求解。以第一组测试数据解释差分约束系统及构造求解。
设三个军营的人数分别为A1,A2,A3,容量为C1,C2,C3,前n个军营的总人数为Sn,则可以列出以下不等式组。
⑴第i个大营到第j个大营士兵总数至少有k个。
S2 - S0 >= 1100 ---> S0 - S2 <= -1100
S3 - S1 >= 1300 ---> S1 - S3 <= -1300
⑵第i个大营到第j个大营不超过这些兵营容量只和,设d[i]为前i个大营容量总和。
S2 - S0 <= d[2] - d[0] = 3000
S3 - S1 <= d[3] - d[1] = 3000
⑶每个兵营实际人数不超过容量。
A1 <= 1000 ---> S1 - S0 <= 1000
A2 <= 2000 ---> S2 - S1 <= 2000
A3 <= 1000 ---> S3 - S2 <= 1000
⑷Ai>=0
S0 - S1 <= 0
S1 - S2 <= 0
S2 - S3 <= 0
把以上不等式组整理好后,我们就可以构造出一个有向图,构造好图后,我们要求的是 S3 - S0的最小值,即 S3 - S0 >= M ---> S0 - S3 <= -M,求S3到S0的最短路径,长度为-M,最终结果就是M。若无最短路径则输出Bad Estimations。
以上参考自:《图论算法理论、实现及应用》---北京大学出版社
第一道差分约束的题,做完还不是很明白 - -。
代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const long long inf = 10000000000000LL;
const int maxn = 10005;
struct node{
int v;
long long w;
node(int _v, long long _w){
v = _v; w = _w;
}
};
int n,m;
int c[maxn]; //每个兵营的人数限制
long long d[maxn]; //前i个兵营的人数总和
vector<node> list[maxn];
long long dist[maxn];//for spfa
int cnt[maxn]; //判断负环
bool inq[maxn];
bool input(){
if(scanf("%d%d",&n,&m) == EOF) return false;
for(int i = 1; i <= n; i++) scanf("%d",&c[i]);
//求和
d[0] = 0;
for(int i = 1; i <= n; i++) d[i] = d[i-1] + c[i];
//clear
for(int i = 0; i <= n; i++) list[i].clear();
int u,v,w;
for(int i = 0; i< m; i++){
scanf("%d%d%d",&u,&v,&w);
//情形1
list[v].push_back(node(u-1,-w));
//情形2
list[u-1].push_back(node(v,d[v]-d[u-1]));
}
for(int i = 1; i <= n; i++){
//情形3
list[i-1].push_back(node(i,c[i]));
//情形4
list[i].push_back(node(i-1,0));
}
return true;
}
bool spfa(int s){
queue<int> q;
for(int i = 0; i <= n; i++){
dist[i] = inf;
inq[i] = false;
cnt[i] = 0;
}
dist[s] = 0;
q.push(s);
cnt[s]++;
while(!q.empty()){
int u = q.front(); q.pop(); inq[u] = false;
if(cnt[u] >= n) return false;
for(int i = 0; i < list[u].size(); i++){
int v = list[u][i].v;
long long w = list[u][i].w;
if(dist[u] + w < dist[v]){
dist[v] = dist[u] + w;
if(!inq[v]){
q.push(v); inq[v] = true; cnt[v]++;
}
}
}
}
return true;
}
void solve(){
if(spfa(n)){
printf("%lld\n",-dist[0]);
}
else{
printf("Bad Estimations\n");
}
}
int main(){
while(input()){
solve();
}
return 0;
}