对于一系列约束条件进行转化建图,最终转化为最短路的模型。

如给定以下条件:
$$
x_2-x_1\leq c_1
$$

$$
x_3-x_2\leq c_2
$$

$$

$$

$$
x_n-x_{n-1}\leq c_{n-1}
$$

求 $max(x_n-x_1)$ 。即 $x_n-x_1\leq c$ ,求 $c$ 的最小值。注意到约束关系 $x_i-x_j\leq c$ 类似于最短路的关系 $dis[v]\leq dis[u]+w(u,v)$ ,对比可以得到:建立边 $add(j,i,c)$ ,然后跑spfa最短路(有负权边),得到的值即为要求的最大值。若有负环,那么无解。

若得到的关系为 $x_i-x_j\geq c$ ,那么可以转化为 $x_j\leq x_i-c$ ,建边 $add(i,j,-c)$ 。

为了判断连通性,可以建立超级源点,从源点向所有点建立 $add(0,i,0)$ ,并且跑一遍spfa(0)。

例:Layout G

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define main mian
using namespace std;
const int N=1005;
const int M=40005;
int n,ml,md,a,b,d;
struct EDGE
{
int nxt,to,wei,;
}edge[M];
int head[N],tot;
inline void add(int x,int y,int v)
{
edge[++tot].nxt=head[x];
edge[tot].to=y;
edge[tot].wei=v;
head[x]=tot;
}
queue<int> q;
int vis[N],dis[N],circle[N];
void spfa(int s)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(circle,0,sizeof(circle));
q.push(s);
vis[s]=1,dis[s]=0;
while(!q.empty())
{
int now=q.front(); q.pop(); vis[now]=0;
for(int i=head[now];i;i=edge[i].nxt)
{
int tt=edge[i].to;
if(dis[now]+edge[i].wei<dis[tt])
{
dis[tt]=dis[now]+edge[i].wei;
circle[tt]=circle[now]+1;
if(circle[tt]>=n)
{
puts("-1");exit(0);
}
if(!vis[tt])
{
vis[tt]=1;
q.push(tt);
}
}
}
}

}
int main()
{
int n;
scanf("%d%d%d",&n,&ml,&md);
for(int i=1;i<=n;i++) add(0,i,0);
for(int i=1;i<=ml;i++)
{
scanf("%d%d%d",a,b,d);
add(a,b,d);
}
for(int i=1;i<=md;i++)
{
scanf("%d%d%d",a,b,d);
add(b,a,-d);
}
spfa(0);
spfa(1);
if(dis[n]==INF) puts("-2");
else printf("%d",dis[n]);
return 0;
}