1170. 排队布局
题目链接
1170. 排队布局
当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些。
农夫约翰有 \(N\) 头奶牛,编号从 \(1\) 到 \(N\),沿一条直线站着等候喂食。
奶牛排在队伍中的顺序和它们的编号是相同的。
因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上。
如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标。
一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数 \(L\)。
另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数 \(D\)。
给出 \(M_L\) 条关于两头奶牛间有好感的描述,再给出 \(M_D\) 条关于两头奶牛间存有反感的描述。
你的工作是:如果不存在满足要求的方案,输出-1;如果 \(1\) 号奶牛和 \(N\) 号奶牛间的距离可以任意大,输出-2;否则,计算出在满足所有要求的情况下,\(1\) 号奶牛和 \(N\) 号奶牛间可能的最大距离。
输入格式
第一行包含三个整数 \(N,M_L,M_D\)。
接下来 \(M_L\) 行,每行包含三个正整数 \(A,B,L\),表示奶牛 \(A\) 和奶牛 \(B\) 至多相隔 \(L\) 的距离。
再接下来 \(M_D\) 行,每行包含三个正整数 \(A,B,D\),表示奶牛 \(A\) 和奶牛 \(B\) 至少相隔 \(D\) 的距离。
输出格式
输出一个整数,如果不存在满足要求的方案,输出-1;如果 \(1\) 号奶牛和 \(N\) 号奶牛间的距离可以任意大,输出-2;否则,输出在满足所有要求的情况下,\(1\) 号奶牛和 \(N\) 号奶牛间可能的最大距离。
数据范围
\(2 \le N \le 1000\),
\(1 \le M_L,M_D \le 10^4\),
\(1 \le L,D \le 10^6\)
输入样例:
4 2 1
1 3 10
2 4 20
2 3 3
输出样例:
27
解题思路
差分约束
由于顺序与编号相同,即有 \(x_i\leq x_{i+1}\),另外对于 \(ml\) 对关系,任意地,\(a<b\),有 \(x_b-x_a\leq l\),对于 \(md\) 对关系,任意地,\(a<b\),有 \(x_b-x_a\geq d\),判断无解需要建立虚拟源点,假设所有的 \(x_i\leq 0\),\(0\) 即为源点,另外由于要求 \(d[n]-d[1]\) 的最大值,而将 \(0\) 作为虚拟源点求的是每个 \(x_i\) 的最大值,而不是 \(d[1]\) 和 \(d[n]\) 的相对最大值,可以将 \(1\) 作为源点再求一遍 \(spfa\) 即可,如果 \(1\) 到不了 \(n\),说明两个点没有关系距离可以任意大
- 时间复杂度: \(O(kn)\)
代码
// Problem: 排队布局
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1172/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=1e3+5;
int n,ml,md;
int cnt[N],d[N];
bool v[N];
vector<PII> adj[N];
bool spfa(int sz)
{
memset(cnt,0,sizeof cnt);
memset(v,0,sizeof v);
memset(d,0x3f,sizeof d);
queue<int> q;
for(int i=1;i<=sz;i++)
{
d[i]=0;
q.push(i);
v[i]=true;
}
while(q.size())
{
int x=q.front();
q.pop();
v[x]=false;
for(auto t:adj[x])
{
int y=t.fi,w=t.se;
if(d[y]>d[x]+w)
{
d[y]=d[x]+w;
cnt[y]=cnt[x]+1;
if(cnt[y]>=n)return false;
if(!v[y])v[y]=true,q.push(y);
}
}
}
return true;
}
int main()
{
cin>>n>>ml>>md;
for(int i=1;i+1<=n;i++)adj[i+1].pb({i,0});
for(int i=1;i<=ml;i++)
{
int a,b,l;
cin>>a>>b>>l;
if(a>b)swap(a,b);
adj[a].pb({b,l});
}
for(int i=1;i<=md;i++)
{
int a,b,d;
cin>>a>>b>>d;
if(a>b)swap(a,b);
adj[b].pb({a,-d});
}
if(!spfa(n))puts("-1");
else
{
spfa(1);
if(d[n]==0x3f3f3f3f)puts("-2");
else
cout<<d[n];
}
return 0;
}