差分约束关键在于明白为什么可以转化为三角不等式。
还有对于不等式 Xi - Xj <= c,要转化为边<Vj, Vi>。
这ZOJ2770自己分析的还是挺正确的。
具体分析不写了,附个代码= = 加注释可能稍微比较乱。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define clr(x) memset(x,0,sizeof(x))
#define fp1 freopen("in.txt","r",stdin)
#define fp2 freopen("out.txt","w",stdout)
#define pb push_back
#define INF 0x3c3c3c3c3c
typedef long long LL;
struct Edge {
LL from, to, dist;
};
const int maxn = 1e6;
struct BF{ //结点编号应该从0开始。 应该可以不从0开始
int n;
vector<Edge> edges;
vector<int> G[maxn];
bool inq[maxn]; //队列优化spfa判断是否边已加入
LL d[maxn];
int p[maxn]; //最短路中的上一条弧
int is_neg[maxn]; //进队次数 用于判断是否有负权环
void init()
{
for(int i = 0;i <= n;i++) G[i].clear();
edges.clear();
}
void addedge(LL from, LL to, LL dist) //单向边操作
{
//printf("%d %d %d~\n", from, to, dist);
edges.push_back((Edge){from, to, dist});
int len = edges.size();
G[from].push_back(len - 1);
}
int spfa(LL be) //可返回bool判断负权环
{
memset(inq, 0, sizeof(inq));
memset(p, 0, sizeof(p));
memset(is_neg, 0, sizeof(is_neg)); //注释用于判断负环
queue<int> Q;
for(int i = 0;i <= n;i++)
d[i] = INF;
d[be] = 0;
Q.push(be);
inq[be] = true;
while(!Q.empty()) // 非空~
{
int u = Q.front(); Q.pop();
inq[u] = false;
for(int i = 0;i < G[u].size();i++) {
Edge &e = edges[G[u][i]];
if(d[e.to] > d[u] + e.dist) {
//这地方把想要输入的值已经转化为e.dist了
d[e.to] = d[u] + e.dist;
p[e.to] = u; //G[u][i]存的是一条边的信息哪不存在标号 直接改成u
if(!inq[e.to]) {
Q.push(e.to);
inq[e.to] = true;
if(++is_neg[e.to] > n) return false;
}
}
//else...
}
}
return true;
}
}test;
LL sold[1000+10];
LL sum[1000+10];
int main()
{
//fp1;
LL n, m, a, b, c;
while(scanf("%lld %lld", &n, &m) == 2){
test.n = n;
test.init();
clr(sold);
clr(sum);
for(int i = 1;i <= n;i++){
scanf("%lld", &sold[i]);
sum[i] = sum[i-1] + sold[i];
test.addedge(i,i-1,0); //Si - Si-1 > 0 每个兵营的数目不能小于0
test.addedge(i-1,i,sold[i]); //最多容纳sold[i];
}
//puts("-----------------");
for(int i = 1;i <= m;i++){
scanf("%lld %lld %lld", &a, &b, &c);
test.addedge(b,a-1,-c); //a---b至少有c个人
//test.addedge(a-1,b,sum[b]-sum[a-1]); //a---b最多有x人
}
if(!test.spfa(n)){
puts("Bad Estimations");
//printf("%d\n", test.d[0]);
}
else printf("%d\n", -test.d[0]);
//
// test.n = 3;
// test.addedge(1,2,5);
// test.addedge(2,3,6);
// if(!test.spfa(1)) puts("hehe");
// else printf("%d %d %d\n",test.d[1],test.d[2],test.d[3]);
}
return 0;
}