当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些。
农夫约翰有 N 头奶牛,编号从 1 到 N,沿一条直线站着等候喂食。
奶牛排在队伍中的顺序和它们的编号是相同的。
因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上。
如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标。
一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数 L。
另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数 D。
给出 ML 条关于两头奶牛间有好感的描述,再给出 MD 条关于两头奶牛间存有反感的描述。
你的工作是:如果不存在满足要求的方案,输出-1;如果 1 号奶牛和 N 号奶牛间的距离可以任意大,输出-2;否则,计算出在满足所有要求的情况下,1 号奶牛和 N 号奶牛间可能的最大距离。
输入格式
第一行包含三个整数 N,ML,MD。
接下来 ML 行,每行包含三个正整数 A,B,L,表示奶牛 A 和奶牛 B 至多相隔 L 的距离。
再接下来 MD 行,每行包含三个正整数 A,B,D,表示奶牛 A 和奶牛 B 至少相隔 D 的距离。
输出格式
输出一个整数,如果不存在满足要求的方案,输出-1;如果 1 号奶牛和 N 号奶牛间的距离可以任意大,输出-2;否则,输出在满足所有要求的情况下,1 号奶牛和 N 号奶牛间可能的最大距离。
数据范围
2≤N≤1000,
1≤ML,MD≤104,
1≤L,D≤106
输入样例:
4 2 1
1 3 10
2 4 20
2 3 3
输出样例:
27
思路
很明显 题目给的就是 xb-xa<=l xb-xa>=d 差分约束的题目
题目所求1到n间的最大距离
求最短路求Xk<=0 的最大解
-1 即存在负环 -2 即到达不了n点
注意
存在这样的负环 与超级源点相连的负环
3 1 1
2 3 2
2 3 3
spfa如果从1开始走并不会判断出这个负环
而spfa 只从0开始走,如果边权都为正值,dist[i] 将全更新为0 如
4 2 1
1 3 10
2 4 20
2 3 3
答案显然不对
所以需要先走一遍spfa(0)判断是否存在负环
再走一遍spfa(1) 判断能否走到n 以及1到n的最大距离
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int h[N],idx,ne[N],e[N],w[N];
void add(int a,int b,int c){
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int n,ml,md;
int dist[N],st[N],se[N];
int spfa(int s){
memset(se,0,sizeof se);
memset(st,0,sizeof st);
memset(dist,0x3f,sizeof dist);//初始化 spfa用了两次
queue<int> q; q.push(s);dist[s]=0;st[s]=1,se[s]=1;
while(q.size()){
int t=q.front();q.pop();st[t]=0;
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(dist[j]>dist[t]+w[i]){
dist[j]=dist[t]+w[i];
se[j]=se[t]+1; if(se[j]>n+1) return -1;//负环判断 从0开始的 n+1 从1开始的 n 直接写成n+1
if(!st[j]) q.push(j),st[j]=1;
}
}
}
return dist[n];
}
int main(){
cin>>n>>ml>>md;
memset(h,-1,sizeof h);
for(int i=1;i<=ml;i++){
int a,b,c;cin>>a>>b>>c;
add(a,b,c);
}
for(int i=1;i<=md;i++){
int a,b,c;cin>>a>>b>>c;
add(b,a,-c);
}
for(int i=1;i<=n;i++) add(i+1,i,0);// 后一头牛 要比前一头牛 距离大 x(i)-x(i+1)<=0
for (int i = 1; i <= n; i++) {//加入超级源点
add(0, i, 0);
}
int j=spfa(0);
if(j==-1) cout<<-1;
else {
int t=spfa(1);
if(t==0x3f3f3f3f) cout<<-2; else cout<<dist[n];
}
return 0;
}