题目:

不难看出题意主要是给出ml+md个格式为xi-xj<=ak的不等式,xi-xj为i,j俩头牛的距离,要我们求x1-xn的最大值。

经过上下加减我们可以将这几个不等式化成x1-xn<=a1+a2+a3+a4+....+ak,在这加减的过程中我们不难看到dijstra的身影,这加加减减的过程不正是松弛操作吗!

这时我们就得到了正解——差分约束算法,此算法主要用于处理差分约束系统:如果一个系统由n个变量和m个约束条件组成,形成m个形如ai-aj≤k的不等式(i,j∈[1,n],k为常数),则称其为差分约束系统。

结论:求解差分约束系统,都可以转化成图论的单源最短路径(或最长路径)问题。

关于差分约束与最短路模型的关系

我们观察上面例子中的不等式,都是x[i] - x[j] <= a[k],可以进行移项,成为x[i] <= x[j] + a[k],我们令a[k] = w(j, i),dis[i]=x[i],并使i=v,j=u,那么原始就变为:dis[u]+w(u,v)>=dis[v],于是可以联想到最短路模型中的一部分代码

if(dis[u]+w(u,v)<=dis[v])
{
dis[v]=dis[u]+w(u,v);
}

这不正与松弛操作相似吗?

但是好像不等号方向刚好相反,但其实这并不矛盾

上面的代码要实现的是使dis[u]+w(u,v)>dis[v],而对于不等式,我们进行建边的操作:对于每个不等式 x[i] - x[j] <= a[k],对结点 j 和 i 建立一条 j -> i的有向边,边权为a[k],求x[n-1] - x[0] 的最大值就是求 0 到n-1的最短路,两者刚好吻合。所以求解差分约束问题就转化为了最短路问题。

问题解的存在性

由于在求解最短路时会出现存在负环或者终点根本不可达的情况,在求解差分约束问题时同样存在

(1)存在负环

如果路径中出现负环,就表示最短路可以无限小,即不存在最短路,那么在不等式上的表现即X[n-1] - X[0] <= T中的T无限小,得出的结论就是 X[n-1] - X[0]的最大值不存在。在SPFA实现过程中体现为某一点的入队次数大于节点数。(貌似可以用sqrt(num_node)来代替减少运行时间)

(2)终点不可达

这种情况表明X[n-1]和X[0]之间没有约束关系,X[n-1] - X[0]的最大值无限大,即X[n-1]和X[0]的取值有无限多种。在代码实现过程中体现为dis[n-1]=INF。

参考的文章链接:https://blog.csdn.net/my_sunshine26/article/details/72849441

注意

1.因为本题中可能存在负权环(众所周知dijstra在碰到这个玩意时完全没有办法)所以我们需要用到SPFA

2.后md个不等式题目一开始给的是:xj-xi>=a 我们可以推出xi-xj<=-a(这在之后的建图处理中会用到)注意负权边。

3.题目所给的条件不一定是对的,所以我们需要跑两次SPFA判断图是不是联通的。(因为洛谷上有3个坑逼数据)

代码:

此为没有考虑条件不正确的情况的代码,70分(洛谷上),在联赛是应该是100分的

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int N=1005;
const int M=40005;
int n,ml,md;
struct EDGE{
int next,to,w;
}edge[M];
int head[N],tot;
void add(int x,int y,int v){
edge[++tot].next=head[x];
edge[tot].to=y;
edge[tot].w=v;
head[x]=tot;
}
queue<int> q;
int vis[N],dis[N],circle[N];//circle为指向tt的个数
void spfa(int s){
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(circle,0,sizeof(circle));
q.push(s);
vis[s]=1,dis[s]=0;
while(!q.empty()){
int now=q.front();
q.pop();
vis[now]=0;
for(int i=head[now];i;i=edge[i].next){
int tt=edge[i].to;
if(dis[now]+edge[i].w<dis[tt]){
dis[tt]=dis[now]+edge[i].w;
circle[tt]=circle[now]+1;
if(circle[tt]>=n){//指向tt的边超过n个自然是不满足条件的
puts("-1");exit(0);
}
if(!vis[tt]){
vis[tt]=1;
q.push(tt);
}
}
}
} }
int main(){
scanf("%d%d%d",&n,&ml,&md);
for(int i=1;i<=ml;i++){
int a,b,d;
scanf("%d%d%d",&a,&b,&d);
add(a,b,d);//a-b<=d
}
for(int i=1;i<=md;i++){
int a,b,d;
scanf("%d%d%d",&a,&b,&d);
add(b,a,-d);//b-a>=d ==> a-b<=-d
}
spfa(1);
if(dis[n]>1e8){puts("-2");return 0;}
printf("%d",dis[n]);
return 0;
}

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,ml,md,a,b,c,fst[10100],nex[50010],v[50010],w[50010],cnt,vis[10100],dis[10100],tim[10100];
queue<int> q;
void add(int a,int b,int c)
{
nex[++cnt]=fst[a];
fst[a]=cnt;
v[cnt]=b;
w[cnt]=c;
return ;
}
int spfa(int k)
{
memset(dis,0x7f/3,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(tim,0,sizeof(tim));
q.push(k);
dis[k]=0;
vis[k]=1;
while(!q.empty())
{
int u=q.front();
//cout<<u<<" ";
q.pop();
tim[u]++;
vis[u]=0;
if(tim[u]>n)
return -1;
for(int i=fst[u];i!=-1;i=nex[i])
{
if(dis[v[i]]>dis[u]+w[i])
{
dis[v[i]]=dis[u]+w[i];
if(!vis[v[i]])
{
q.push(v[i]);
vis[v[i]]=1;
}
}
}
}
/*cout<<endl;
for(int i=1;i<=n;i++)
{
cout<<dis[i]<<" ";
}*/
if(dis[n]>1e8)
return -2;
return dis[n];
}
int main()
{
memset(fst,-1,sizeof(fst));
cin>>n>>ml>>md;
for(int i=1;i<=ml;i++)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
for(int i=1;i<=md;i++)
{
scanf("%d%d%d",&a,&b,&c);
add(b,a,-c);
}
for(int i=1;i<n;i++)
{
add(i+1,i,0);
}
for(int i=1;i<=n;i++)
{
add(0,i,0);
}
int sp=spfa(0);
if(sp<=-1)
{
cout<<sp;
return 0;
}
else
{
cout<<spfa(1);
}
//cout<<" "<<sp;
return 0;
}

  

代码参考:https://www.luogu.org/blog/roy1994/solution-p4878  https://www.luogu.org/blog/mikasamikasa/solution-p4878

差分约束算法————洛谷P4878 [USACO05DEC] 布局的更多相关文章

  1. 洛谷P4878 [USACO05DEC]layout布局

    题目描述 正如其他物种一样,奶牛们也喜欢在排队打饭时与它们的朋友挨在一起.\(FJ\) 有编号为 \(1\dots N\) 的 \(N\) 头奶牛 \((2\le N\le 1000)\).开始时,奶 ...

  2. 【最短路·差分约束】洛谷P1250

    题目描述 一条街的一边有几座房子.因为环保原因居民想要在路边种些树.路边的地区被分割成块,并被编号成1..N.每个部分为一个单位尺寸大小并最多可种一棵树.每个居民想在门前种些树并指定了三个号码B,E, ...

  3. 【洛谷P4878】布局

    题目大意:给定一个长度为 N 的递增序列,有 M 组差分约束关系,求满足这些约束关系时,第一个数和第 N 个数的差是多少. 题解:首先,能否满足约束关系需要判断一下负环,若满足约束关系,再从第一个点 ...

  4. 洛谷 P4878 [USACO05DEC]layout布局

    题面链接 sol:差分约束系统裸题,根据a+b<=c建个图跑个最短路就没了... #include <queue> #include <cstdio> #include ...

  5. P5960 差分约束算法模板

    差分约束 差分约束,一般用来解决有\(n\)个未知数,\(m\)个不等式方程的问题,形如: \[\begin{cases} \ x_{a_1}-x_{b_1}\leq y_1\\ \ x_{a_2}- ...

  6. 鉴于spfa基础上的差分约束算法

    怎么搞?        1. 如果要求最大值      想办法把每个不等式变为标准x-y<=k的形式,然后建立一条从y到x权值为k的边,变得时候注意x-y<k =>x-y<=k ...

  7. P4878 [USACO05DEC] 布局

    题面lalala 这居然是个紫题???原谅我觉得这题是模板... 这个这个,这题的算法呢其实是一个叫差分约束的东西,也是今天下午我们机房的重点,如果不知道这个差分约束是个啥的人呢,自行百度一下谢谢.. ...

  8. Luogu P4878 [USACO05DEC]布局

    题目 差分约束模板. 注意判负环需要建一个超级源点到每个点连一条\(0\)的边.因为\(1\)不一定能到达所有的点. #include<bits/stdc++.h> #define pi ...

  9. P5960 【模板】差分约束算法

    题目描述 给出一组包含 $m$ 个不等式,有 $n$ 个未知数的形如: 的不等式组,求任意一组满足这个不等式组的解. 输入格式 第一行为两个正整数 $n,m$,代表未知数的数量和不等式的数量. 接下来 ...

随机推荐

  1. [唐胡璐]Selenium技巧- 如何处理Table

    由于webdriver中没有专门的table类,所以我们需要简单的封装出一个易用易扩展的Table类来帮助简化代码。 以下是我之前用C#语言来实现的一个简单的封装: 只是一个大概的思路,有些具体实现就 ...

  2. Vue-main.js中的一些配置

    import Vue from 'vue' import App from './App.vue' import router from './router' import store from '. ...

  3. c++对c的扩展----引用类型

    变量是一个内存的别名,程序通过变量名使用内存空间,当然一个内存空间可以起多个别名么? 答案:可以,这就是c++中引用的由来,引用就是给变量起别名 引用是c++的概念!!!况且声明引用的符号&十 ...

  4. 后端数据中含有html标签和css样式,前端如何转译展示样式效果。

    后端含有html标签和css样式的数据: domain="<span style='color:red'>www.baidu.com</span>" (vu ...

  5. Mac: ld: library not found for -lgcc_s.10.4

    Mac: ld: library not found for -lgcc_s.10.4   Checking for cc... ld: library not found for -lgcc_s.1 ...

  6. mysql 解决忘记密码 mysql5.7 远程登录不上MySQL(解决腾讯服务器初始mysql密码问题)

    一.修改MySQL启动配置文件 #如果不知道配置文件,先查找find / -name my.cnf#编辑配置文件 vim /etc/my.cnf 在[mysql]  下面第一行加入 skip-gran ...

  7. Python 10.2.1

  8. P2215 [HAOI2007]上升序列 DP

    这个字典序海星 思路:\(DP\) 提交:4次 错因:刚开始把字典序理解错了,怒看题解一脸懵逼:后来往前跳的时候又没有管上升\(QwQ\)窝太菜了. 题解: 所谓的字典序是相对位置!!!而不是元素本身 ...

  9. jQuery.map(arr|obj,callback)

    jQuery.map(arr|obj,callback) 概述 将一个数组中的元素转换到另一个数组中.广州大理石机械构件 作为参数的转换函数会为每个数组元素调用,而且会给这个转换函数传递一个表示被转换 ...

  10. 配置文件的属性ENC加密

    转载:https://www.cnblogs.com/zqyx/p/9687136.html 在micro service体系中,有了config server,我们可以把配置存放在git.svn.数 ...