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;
}
posted @ 2022-08-12 18:31  zyy2001  阅读(23)  评论(0编辑  收藏  举报