题目来源:http://poj.org/problem?id=3169
思路来自:https://blog.csdn.net/mengxiang000000/article/details/52613328
差分约束系统题目。题目要求即是求出an-a1的最大值。
如果只考虑ml的情况,则可以推出:
a1-a2<=k1; -- 1
a2-a3<=k2; -- 2
a1-a3<=k3; -- 3
1.2式可以推得a1-a3<=k1+k2
由此a1-a3<=min(k1+k2,k3).
对于md的情况:
a1-a2>=k1可以转化为a2-a1<=-k1.因此可以转化为上一种的形式。
最短路可以用spfa求出。
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define ll long long
#define ull unsigned long long
#define BUG printf("************\n")
#define STOP getchar()
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 1e3 + 10;
const int maxm = 1e4 + 10;
const double eps = 1e-8;
ll gcd(ll a,ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a,ll b) {
return a / gcd(a, b) * b;
}
struct edge {
int to, next, vi;
} e[maxn * maxn];
int n, ml, md, cnt, head[maxn], dis[maxn], g[maxn][maxn], inq[maxn];
bool vis[maxn];
queue<int> q;
void ins(int x,int y,int z) {
e[++cnt].to = y;
e[cnt].next = head[x];
e[cnt].vi = z;
head[x] = cnt;
}
int main() {
/*
freopen("equal.in", "r", stdin);
freopen("equal.out", "w", stdout);
*/
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
while (cin >> n >> ml >> md) {
cnt = 0;
memset(head, 0, sizeof(head));
memset(g, 63, sizeof(g));
int x, y, z;
for (int i = 1; i <= ml; ++i) {
cin >> x >> y >> z;
g[x][y] = min(g[x][y], z);
}
for (int i = 1; i <= md; ++i) {
cin >> x >> y >> z;
g[y][x] = min(g[y][x], -z);
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (g[i][j] < 1e8) {
ins(i, j, g[i][j]);
}
}
}
memset(dis, 63, sizeof(dis));
memset(vis, 0, sizeof(vis));
memset(inq, 0, sizeof(inq));
while (!q.empty())q.pop();
bool ok = 1;
q.push(1);
vis[1] = 1;
dis[1] = 0;
inq[1]++;
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = head[x]; i; i = e[i].next) {
int v = e[i].to;
if (dis[v] > dis[x] + e[i].vi) {
dis[v] = dis[x] + e[i].vi;
if (vis[v] == 0) {
vis[v] = 1;
q.push(v);
inq[v]++;
}
if (inq[v] > n) {
ok = 0;
break;
}
}
}
if (!ok)break;
vis[x] = 0;
}
if (!ok)cout << -1 << endl;
else if (dis[n] > 1e8)cout << -2 << endl;
else cout << dis[n] << endl;
}
return 0;
}