题目请戳这里
题目大意:刘备有n个军营,陆逊要烧之,所以要事先估计刘备有多少人。已知刘备第i个军营不超过ci个人,通过侦查,陆逊有m个消息,表示刘备第i个军营到第j个军营至少有k人,现在要估计刘备军队至少多少人。
题目分析:差分约束。根据题意可以整理出一些不等式组:
1。首先每个军营的人数0<=ai<=ci,用si表示前i个军营人数总和。那么就有si - si-1 >= 0即si-1 - si <= 0,以及si - si-1 <= ci
2。第i个军营到第j个军营至少k人,sj - si-1 >= k,即si-1 - sj <= -k
3。第i个军营到第j个军营人数不能超过sigma(ci~cj),即sj - si-1 <= sigma(ci~cj)
这样差分约束系统就建立好了。再看要求什么。
题目要求估计刘备军队人数,即sn-s0,那么以n为原点求最短路,就能满足上面的约束关系,那么答案就是n到0的距离取反,即-s[0]。
详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 1005; const int M = 10005; const int INF = 0x3f3f3f3f; int n,m; int c[N]; int head[N]; struct node { int to,val,next; }g[M<<2]; int num; bool ok; bool flag[N]; int dis[N]; int queue[N]; int in[N]; int front,rear; void build(int s,int e,int v) { g[num].to = e; g[num].val = v; g[num].next = head[s]; head[s] = num++; } void SPFA() { int i,j; for(i = 0;i <= n;i ++) { flag[i] = false; dis[i] = INF; in[i] = 0; } dis[n] = 0; flag[n] = true; in[n] ++; front = rear = 0; queue[rear ++] = n; while(front < rear) { int u = queue[front ++]; flag[u] = false; for(i = head[u];i != -1;i = g[i].next) { if(dis[g[i].to] > dis[u] + g[i].val) { dis[g[i].to] = dis[u] + g[i].val; if(flag[g[i].to] == false) { if(in[g[i].to] == n - 1) { ok = true; return; } in[g[i].to] ++; flag[g[i].to] = true; queue[rear ++] = g[i].to; } } } } } int main() { int i,j,k; while(scanf("%d%d",&n,&m) != EOF) { num = 0; memset(head,-1,sizeof(head)); c[0] = 0; for(i = 1;i <= n;i ++) { scanf("%d",&c[i]); build(i - 1,i,c[i]); c[i] += c[i - 1]; build(i,i - 1,0); } while(m --) { scanf("%d%d%d",&i,&j,&k); build(i - 1,j,c[j] - c[i - 1]); build(j,i - 1,-k); } ok = false; SPFA(); if(ok) puts("Bad Estimations"); else printf("%d\n",dis[n] - dis[0]); } return 0; } //50ms 676k