【差分约束系统】 layout奶牛的站位 本校woj2239

#2239 奶牛的站位Layout

描述
有 N 头奶牛正在排队,它们的编号为 1 到 N,约翰要给它们安排合适的排队位置,满足以下条 件:

• 首先,所有奶牛要站在一条直线上。由于是排队,所以编号小的奶牛要靠前,不能让编号大的 奶牛插队。但同一个位置可以容纳多头奶牛,这是因为它们非常苗条的缘故

• 奶牛喜欢和朋友靠得近点。朋友关系有 F 对,其中第 Ai 头奶牛和第 Bi 头奶牛是第 i 对朋友, 它们的距离不能超过 Ci

• 奶牛还要和讨厌的同类保持距离。敌对关系有 E 对,其中第 Xi 头奶牛和第 Yi 头奶牛是第 i 对 敌人,它们的距离不能少于 Zi

你能否帮助约翰找到一个合理的站位方法,满足所有奶牛的要求,而且让 1 号奶牛和 N 号奶牛间的 距离尽量大
/

第一行:三个整数 N, F 和 E, 2 ≤ N ≤ 1000, 1 ≤ F; E ≤ 10000

• 第二行到第 F + 1 行:第 i + 1 行有三个整数 Ai, Bi 和 Ci, 1 ≤ Ai; Bi ≤ N; 1 ≤ Ci ≤ 1e6

• 第 F + 2 行到第 F + E + 1 行:第 i + F + 1 行有三个整数 Xi, Yi 和 Zi, 1 ≤ Xi; Yi ≤ N; 1 ≤ Zi ≤ 10^6
///

差分约束模板

1.(前面的不在后面的后面:)注意不能写成
x[i]-x[i+1]<=0;

答案求的是 最大距离

2.注意实际含义
(距离要加绝对值,所以对于|x[i]-x[i+1]| 和x[i]-x[i+1]单减关系,本来的最短路又成为了最长路。。)
朋友和敌人的关系也是如此
变形之前的不等式要把编号大的放在前面(规定了编号大的>=编号小的)

水谷上有些题解没有考虑到这种情况,直接用数据:
2 1 0
2 1 5
hack掉

3.判断无解每一个点都要遍历


#include<bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define cs const
#define ll long long
cs int N=1e5+10;
int nxt[N],to[N],w[N],cnt=0,head[N];
inline void _add(int u,int v,int ww){
	nxt[++cnt]=head[u];head[u]=cnt;to[cnt]=v;w[cnt]=ww;
}
int dis[N],tot[N],vis[N],flag;
int n,F,E;
inline void spfa(int st){
	queue<int> q;
	q.push(st);dis[st]=0;
	while(!q.empty()){
		int u=q.front();q.pop();vis[u]=0;
		for(int i=head[u];i;i=nxt[i]){
			int v=to[i];
			if(dis[v]>dis[u]+w[i]){
				dis[v]=dis[u]+w[i];
				++tot[v];
				if(tot[v]>n){
					cout<<"-1";
					exit(0); 
				}
				if(!vis[v])vis[v]=1,q.push(v);
			}
		}
	}
	if(st==1&&dis[n]==0x6f6f6f6f)flag=1;
}
signed main(){
	sf("%d%d%d",&n,&F,&E);
	while(F--){
		int a,b,c;sf("%d%d%d",&a,&b,&c);
		if(a<b)swap(a,b);
		_add(b,a,c);
	}
	while(E--){
		int a,b,c;sf("%d%d%d",&a,&b,&c);
		if(a<b)swap(a,b);
		_add(a,b,-c);
	}
	memset(dis,0x6f,sizeof dis);
	for(int i=n;i>=2;--i)_add(i,i-1,0);
	flag=0;
	for(int i=1;i<=n;++i)if(dis[i]==0x6f6f6f6f)spfa(i);
	if(flag)cout<<"-2";
	else cout<<dis[n]<<'\n';
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值