首先题目中的隐含条件是
d[i] <= d[i + 1]
即d[i + 1] + 0 >= d[i]
然后对那ML个条件
d[y] - d[x] <= w -> d[x] + w >= d[y]
对那MD个条件
d[y] - d[x] >= w -> d[y] + (-w) >= d[x]
然后呢就可以加边了。
对于一个不等式 d[u] + w >= d[v] 我们可以加边(u, v , w)
这是由于在一个图里,从s出发,到各个顶点的v最短距离为d[v],那么对一个边(u, v, w) 必然有d[u] + w >= d[v]
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define MAXN 1111
#define MAXM 222222
#define INF 1000000000
using namespace std;
int n, ml, md;
struct Edge
{
int to, cost;
};
vector<Edge>g[MAXN];
queue<int>q;
int dis[MAXN], vis[MAXN], num[MAXN];
void solve(int src, int des)
{
for(int i = 1; i <= n; i++)
dis[i] = INF, vis[i] = 0;
dis[src] = 0;
vis[src] = 1;
q.push(src);
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u] = 0;
for(int i = 0; i < g[u].size(); i++)
{
Edge e = g[u][i];
int v = e.to;
int w = e.cost;
if(dis[u] + w < dis[v])
{
dis[v] = dis[u] + w;
if(!vis[v])
{
if(num[v] > n)
{
printf("-1\n");
return;
}
num[v]++;
q.push(v);
vis[v] = 1;
}
}
}
}
if(dis[des] == INF) printf("-2\n");
else printf("%d\n", dis[des]);
}
int main()
{
int x, y, w;
scanf("%d%d%d", &n, &ml, &md);
for(int i = 0; i < ml; i++)
{
scanf("%d%d%d", &x, &y, &w); // d[y] - d[x] <= w -> d[x] + w >= d[y]
g[x].push_back({y, w});
}
for(int i = 0; i < md; i++)
{
scanf("%d%d%d", &x, &y, &w); // d[y] - d[x] >= w -> d[y] + (-w) >= d[x]
g[y].push_back({x, -w});
}
for(int i = 1; i < n; i++) //d[i + 1] + 0 >= d[i]
g[i + 1].push_back({i, 0});
solve(1, n);
return 0;
}