传送门:牛客
题目描述
正如其他物种一样,奶牛们也喜欢在排队打饭时与它们的朋友挨在一起。FJ 有编号为
1
…
N
1\dots N
1…N 的
N
N
N 头奶牛
(
2
≤
N
≤
1000
)
(2\le N\le 1000)
(2≤N≤1000)。开始时,奶牛们按照编号顺序来排队。奶牛们很笨拙,因此可能有多头奶牛在同一位置上。
有些奶牛是好基友,它们希望彼此之间的距离小于等于某个数。有些奶牛是情敌,它们希望彼此之间的距离大于等于某个数。
给出
M
L
M_L
ML 对好基友的编号,以及它们希望彼此之间的距离小于等于多少;又给出
M
D
M_D
MD 对情敌的编号,以及它们希望彼此之间的距离大于等于多少
(
1
≤
M
L
,
(1\le M_L,
(1≤ML,
M
D
≤
1
0
4
)
M_D\le 10^4)
MD≤104)。
请计算:如果满足上述所有条件,
1
1
1 号奶牛和
N
N
N 号奶牛之间的距离最大为多少。
输入:
4 2 1
1 3 10
2 4 20
2 3 3
输出:
27
一道差分约束的模板题.对于差分约束,网上已经有大量博客对此进行讲解(不乏有讲的非常详细的),所以此处对于差分约束算法我就不在赘述了
接下来主要讲一下为什么差分约束跑最短路得到的是值是最大值,用本题来说,就是为什么我们从1点开始跑差分约束,最后得到的 d i s [ n ] dis[n] dis[n]就是最大的一个解.
对于跑最短路算法,我们有
d
i
s
[
v
]
−
d
i
s
[
u
]
<
w
[
u
]
[
v
]
dis[v]-dis[u]<w[u][v]
dis[v]−dis[u]<w[u][v],等价于
w
e
i
z
h
i
[
v
]
−
w
e
i
z
h
i
[
u
]
<
C
weizhi[v]-weizhi[u]<C
weizhi[v]−weizhi[u]<C,此时我们从u向v连一个有向边.那么当我们从1能到达一个点n,就说明1到n有着一些有向边连接,并且最终指向了n点.用我们原本的式子来说就是肯定存在:
w
e
i
z
h
i
[
v
1
]
−
w
e
i
z
h
i
[
u
]
<
C
weizhi[v1]-weizhi[u]<C
weizhi[v1]−weizhi[u]<C
w
e
i
z
h
i
[
v
2
]
−
w
e
i
z
h
i
[
v
1
]
<
C
2
weizhi[v2]-weizhi[v1]<C2
weizhi[v2]−weizhi[v1]<C2
.
.
.
...
...
w
e
i
z
h
i
[
v
n
]
−
w
e
i
z
h
i
[
v
n
−
1
]
<
C
n
weizhi[v_{n}]-weizhi[v_{n-1}]<Cn
weizhi[vn]−weizhi[vn−1]<Cn
累加一下就是
w
e
i
z
h
i
[
v
n
]
−
w
e
i
z
h
i
[
u
]
<
C
1
+
C
2
+
.
.
.
+
C
n
weizhi[v_{n}]-weizhi[u]<C1+C2+...+Cn
weizhi[vn]−weizhi[u]<C1+C2+...+Cn,此时不妨将我们的
w
e
i
z
h
i
[
u
]
weizhi[u]
weizhi[u]记作0,那么我们的此时的n点和1点的位置距离差就存在一个最大值
(并且假设有多个上述的路径存在,我们肯定是取一个min值,因为我们需要满足所有的约束,与跑最短路并无矛盾)
那么类似的,当我们的1点到达不到某些点时,代表着我们的这些点的距离可以是无穷(可以自己画一画理解);
当我们跑最长路算法时,最后求出的就是最小的一个解
下面是具体的代码部分:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
ll x=0,w=1;char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*w;
}
#define maxn 1000000
const double eps=1e-8;
#define int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
struct Node{
int v,w;
};
vector<Node>edge[maxn];
int dis[maxn],vis[maxn],cnt[maxn];
int n,ml,md;
int Spfa(int S) {
queue<int>q;
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
q.push(S);dis[S]=0;
while(!q.empty()) {
int u=q.front();q.pop();
vis[u]=0;
for(int i=0;i<edge[u].size();i++) {
int v=edge[u][i].v;
if(dis[v]>dis[u]+edge[u][i].w) {
cnt[v]=cnt[u]+1;
if(cnt[v]==n+1) return -1;
dis[v]=dis[u]+edge[u][i].w;
if(!vis[v]) {
q.push(v);
vis[v]=1;
}
}
}
}
return 1;
}
int main() {
n=read();ml=read();md=read();
for(int i=1;i<n;i++) {
edge[i+1].push_back({i,0});
}
for(int i=1;i<=ml;i++) {
int u=read(),v=read(),w=read();
edge[u].push_back({v,w});
}
for(int i=1;i<=md;i++) {
int u=read(),v=read(),w=read();
edge[v].push_back({u,-w});
}
for(int i=1;i<=n;i++) {
edge[0].push_back({i,0});
}
if(Spfa(0)==-1) {
printf("-1\n");
}else {
Spfa(1);
if(dis[n]==int_INF) printf("-2\n");
else cout<<dis[n]<<endl;
}
return 0;
}