题意:
将给定的n头牛按编号大小依次安排在数轴上
给出ml条边,每条边A、B、D表示牛A和牛B的距离不能超过D
再给出md条边,每条边A、B、D表示牛A和牛B的距离不能低于D
求符合要求的最大的牛1到牛n的距离。
题解:
一堆不等式,首先想到差分约束。
差分约束:
要求最大值,则将不等式组转换为小于等于形式,spfa求最短路(因为可能有负环),dis初始化为INF,对于每个形如 的不等式,可得一条j号节点指向i号节点权值为k的有向边。
要求最小值,则将不等式组转换为大于等于形式,spfa求最长路,dis初始化为0(或负无穷?具体看题目),对于每个形如 的不等式,可得一条
j号节点指向i号节点权值为k的有向边。
本题要求最大值。
不等式转换过程中注意本题的隐含条件,编号大的坐标一定大于等于编号小的坐标,所以对于不超过D的边,不等式为 ,对于不低于D的边,不等式为 。
最后spfa求最短路,若有负环,说明无解,输出-1;若从1到n的最短距离为INF,说明无限多解,输出-2;否则,输出最短距离。
代码:
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
#define ll long long
#define db double
#define m_p make_pair
#define p_b push_back
#define For(i,a,b) for(int i=a;i<=b;i++)
#define ls (rt<<1)
#define rs ((rt<<1)|1)
#define mst(a,b) memset(a,b,sizeof(a))
const int MAXN=1e3+5;
const db eps=1e-8;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const int seed=131;
int n,ml,md;
struct Edge{
int v,w;
Edge(int _v=0,int _w=0):v(_v),w(_w){}
};
vector<Edge> G[MAXN];
bool vis[MAXN];
queue<int> q;
int dis[MAXN],cnt[MAXN];
bool spfa(int s,int n){
mst(vis,0);
mst(dis,INF);
mst(cnt,0);
vis[s]=1;
q.push(s);
dis[s]=0;
cnt[s]=1;
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
for(int i=0;i<G[u].size();i++){
Edge &tt=G[u][i];
int v=tt.v,w=tt.w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
cnt[v]++;
if(!vis[v]) vis[v]=1,q.push(v);
if(cnt[v]>n) return true;
}
}
}
return false;
}
int main(){
// freopen("in.txt","r",stdin);
scanf("%d %d %d",&n,&ml,&md);
int u,v,d;
for(int i=1;i<=ml;i++){
scanf("%d %d %d",&u,&v,&d);
G[u].p_b(Edge(v,d));
}
for(int i=1;i<=md;i++){
scanf("%d %d %d",&u,&v,&d);
G[v].p_b(Edge(u,-d));
}
bool f=spfa(1,n);
if(f) cout<<"-1\n";
else if(dis[n]==INF) cout<<"-2\n";
else cout<<dis[n]<<"\n";
return 0;
}