差分约束,我们定义x[i]为第i个营的人数,定义dist[i]=x[0]+x[1]+...x[i],其中x[0]=0,则可知我们要求的为dist[n]。
对于差分不等式,a - b <= c ,建一条 b 到 a 的权值为 c 的边,求的是最短路,得到的是最大值;对于不等式 a - b >= c ,建一条 b 到 a 的权值为 c 的边,求的是最长路,得到的是最小值。这题由于求最小值,所以我们用的是第二种。
对于题目,我们可以有如下约束
Ci有: x[i]=dist[i]-dist[i-1],则有dist[i]-dist[i-1]>=0,且dist[i-1]-dist[i]>=-Ci
i,j,k有: s[j]-s[i-1]>=k
还有: dist[i]>=0,即dist[i]-dist[0]>=0
因为是求最小值,同时图的建立是按照小于等于进行,所以我们就要从负无穷约束到最小值,用SPFA求最长路即可。
SPFA过程中判断是否有环。
-dis[i
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define Edge_count 30000
#define Pnt_count 2000
#define INF 0x1f1f1f1f
struct edge
{
int adj;
int point;
int w;
edge(int a, int p, int ww):adj(a),point(p),w(ww){}
edge():adj(0),point(0),w(0){}
};
edge e[Edge_count];
int dis[Pnt_count];
int c[2000];
bool bellman(int src,int edge_count,int pnt_count)
{
memset(dis,0x1f,sizeof(dis));
dis[src] = 0;
for(int i = 1; i<pnt_count; i++)
{
for( int j = 1; j <= edge_count; j++)
{
if(dis[e[j].adj] < INF && dis[e[j].adj] + e[j].w < dis[e[j].point])
dis[e[j].point] = dis[e[j].adj] + e[j].w;
}
}
for( int j = 1; j <= edge_count; j++)
{
if(dis[e[j].adj] < INF && dis[e[j].adj] + e[j].w < dis[e[j].point])
return 0;
}
return 1;
}
int main()
{
int n,m;
while(~scanf("%d %d",&n, &m))
{
for( int i = 1; i<=n; i++)
scanf("%d",&c[i]);
for( int i = 1; i<=m; i++)
{
int u,v,w;
scanf("%d%d%d",&u, &v, &w);
e[i] = edge(v,u-1,-w);
}
for( int i = 1; i<=n; i++)
{
e[m+i] = edge(i-1,i,c[i]);
e[m+n+i] = edge(i,i-1,0);
}
if(bellman(n,m+n+n,n+1))
cout<<-dis[0]<<endl;
else
cout<<"Bad Estimations"<<endl;
}
}