据说差分约束有很多种,但是我学过的只有SPFA求差分;

我们知道,例如 A-B<=C,那么这就是一个差分约束。

比如说,著名的三角形差分约束,这个大家都是知道的,什么两边之差小于第三边啦,等等等等。

所以说,我们学他干嘛(我们得出结论:学他没用,谢谢大家观看)

咳咳——说正事,我们来看一道例题:【luoguP1993】小K的农场:

题目描述

小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述:

  • 农场a比农场b至少多种植了c个单位的作物,
  • 农场a比农场b至多多种植了c个单位的作物,
  • 农场a与农场b种植的作物数一样多。

但是,由于小K的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。

输入格式:

第一行包括两个整数 n 和 m,分别表示农场数目和小 K 记忆中的信息数目。

接下来 m 行:

如果每行的第一个数是 1,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至少多种植了 c 个单位的作物。

如果每行的第一个数是 2,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至多多种植了 c 个单位的作物。如果每行的第一个数是 3,接下来有 2 个整数 a,b,表示农场 a 种植的的数量和 b 一样多。

输出格式:

如果存在某种情况与小 K 的记忆吻合,输出“Yes”,否则输出“No”。

我们看一看题干,能够发现一些条件:1.A-B>=C,2.A-B<=C,3.A=B。

我们一个一个分析先分析第2个(为什么?等会就明白了)

题中让我们求得是否能够让条件成立,那么就用到我们的SPFA了,怎么用?

还记得SPFA那个更新条件吗

dis[y]>dis[x]+edge[i].w;所以说,让我们反想一下,既然我们求得答案,那么我们肯定想

dis[y]<=dis[x]+edge[i].w

因为这样最后我们就可以求得答案了;

那么如果我们将它推论到差分系统呢,我们想让它成立,那么就要让他限制于一个条件,那么很容易就能懂C应该是edge[i].w;

那么我们推一下,A<=B+C -> A-B<=C。这样我们建一个由B指向A的边,边权为C,那么我们再来看第一个条件就很容易懂了。

这个就直接说了,B-A<=-C,之后就和前面的一样了;

那么来看最后一个条件:A=B。这个应该是初中(应该不是的小学吧QWQ)数学的知识,A>=B && A<=B,就可以实现这个条件的差分替换了;

那么再用上SPFA的judge负环的骚操作就可以了。

这样应该就能写出来这道题了——吗?

你会发现你从1点开始跑会有70分,(其实是水的),为什么呢?

这是因为图可能并不联通,那么你这样跑就会凉凉,那么我们可以建一个超级原点,这样就可以联通了,提交发现60分

!!!怎么还少了QAQ!!!

所以说上面的过程是水的呀,我们会T掉,因为BFS会一直在圈里跑,而圈子又太大,那么SPFA的诟病就出来了(关于SPFA,它死了)

SPFA还没有凉透,因为我们会出现负环,而题中就让我们判断负环,我们没法用其他算法啊!

那么就有了应运而生的SPFA-DFS判负环版本,来看一下代码

bool SPFA(int x){
vis[x]=;//标记在搜索过程中
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(dis[y]>dis[x]+edge[i].w){
dis[y]=dis[x]+edge[i].w;
if(vis[y]) return true;/*循环环出现,也就是负权值不停更新
,那么我们用这个机制就可以return了*/
if(SPFA(y)) return true;
}
}
vis[x]=;//清除标记
return false;//条件成立
}

这样就不会TLE了;

现在来看完整代码(其中有BFS的TLE代码):

Code

 #include<bits/stdc++.h>
#define maxn 10007
using namespace std;
int n,m,head[maxn],cent,vis[maxn],dis[maxn],num[maxn];
struct node{
int next,to,w;
}edge[maxn<<];
queue<int >q; void add(int u,int v,int w){
edge[++cent]=(node){head[u],v,w};head[u]=cent;
} //bool SPFA(int x){
// vis[x]=1,num[x]++,dis[x]=0;
// q.push(x);
// while(!q.empty()){
// int x=q.front();vis[x]=0;q.pop();
// for(int i=head[x];i;i=edge[i].next){
// int y=edge[i].to;
// if(dis[y]>dis[x]+edge[i].w){
// dis[y]=dis[x]+edge[i].w;
// if(!vis[y]){
// q.push(y);
// num[y]++;
// }
// if(num[y]>=n){
// return true;
// }
// }
// }
// }
// return false;
//} bool SPFA(int x){
vis[x]=;//标记在搜索过程中
for(int i=head[x];i;i=edge[i].next){
int y=edge[i].to;
if(dis[y]>dis[x]+edge[i].w){
dis[y]=dis[x]+edge[i].w;
if(vis[y]) return true;/*循环环出现,也就是负权值不停更新
,那么我们用这个机制就可以return了*/
if(SPFA(y)) return true;
}
}
vis[x]=;//清除标记
return false;//条件成立
} int main(){
// freopen("cin.in","r",stdin);
// freopen("cout.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=,s,a,b,c;i<=m;i++){
scanf("%d%d%d",&s,&a,&b);
if(s==){
scanf("%d",&c);
add(a,b,-c);
}else if(s==){
scanf("%d",&c);
add(b,a,c);
}else if(s==){
add(a,b,);
add(b,a,);
}
}
for(int i=;i<=n;i++) add(,i,);//超级源点
memset(dis,0x3f3f3f,sizeof(dis));
dis[]=;//搜索初始化
if(SPFA()) printf("No");
else printf("Yes");
return ;
}

这道题就结束了,再送一道福利题[USACO05DEC]

好了,就这样了。

图论分支-差分约束-SPFA系统的更多相关文章

  1. 【poj3169】【差分约束+spfa】

    题目链接http://poj.org/problem?id=3169 题目大意: 一些牛按序号排成一条直线. 有两种要求,A和B距离不得超过X,还有一种是C和D距离不得少于Y,问可能的最大距离.如果没 ...

  2. O - Layout(差分约束 + spfa)

    O - Layout(差分约束 + spfa) Like everyone else, cows like to stand close to their friends when queuing f ...

  3. 【bzoj2330】: [SCOI2011]糖果 图论-差分约束-SPFA

    [bzoj2330]: [SCOI2011]糖果 恩..就是裸的差分约束.. x=1 -> (A,B,0) (B,A,0) x=2 -> (A,B,1)  [这个情况加个A==B无解的要特 ...

  4. UVA 515 差分约束 SPFA判负

    第一次看这个题目,完全不知道怎么做,看起来又像是可以建个图进行搜索,但题目条件就给了你几个不等式,这是怎么个做法...之后google了下才知道还有个差分约束这样的东西,能够把不等式化成图,要求某个点 ...

  5. poj3159 差分约束 spfa

    //Accepted 2692 KB 1282 ms //差分约束 -->最短路 //TLE到死,加了输入挂,手写queue #include <cstdio> #include & ...

  6. 【BZOJ】2330: [SCOI2011]糖果(差分约束+spfa)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2330 差分约束运用了最短路中的三角形不等式,即d[v]<=d[u]+w(u, v),当然,最长 ...

  7. (简单) POJ 3169 Layout,差分约束+SPFA。

    Description Like everyone else, cows like to stand close to their friends when queuing for feed. FJ ...

  8. poj Layout 差分约束+SPFA

    题目链接:http://poj.org/problem?id=3169 很好的差分约束入门题目,自己刚看时学呢 代码: #include<iostream> #include<cst ...

  9. BZOJ.4500.矩阵(差分约束 SPFA判负环 / 带权并查集)

    BZOJ 差分约束: 我是谁,差分约束是啥,这是哪 太真实了= = 插个广告:这里有差分约束详解. 记\(r_i\)为第\(i\)行整体加了多少的权值,\(c_i\)为第\(i\)列整体加了多少权值, ...

随机推荐

  1. Quartus prime16.0 组合逻辑always块中敏感向量表不全

    前言 组合逻辑always块中向量敏感表不全导致的警告. 流程 1.对于如下代码块: always @(nstate /*or master_din or master_dout_reg*/) beg ...

  2. 【HDU - 5845】Best Division(xor-trie、01字典树、dp)

    BUPT2017 wintertraining(15) #7E 题意 把数组A划分为k个区间,每个区间不超过L长度,每一个区间异或和之和为S.现在求:S不超过X,区间个数的最大值. 且A是这样给你的: ...

  3. windows 路由转发

    netsh interface ipv6 install 将内网的2433端口转发到外网的11111端口netsh interface portproxy add v4tov4 listenaddre ...

  4. Before NOIP 2018

    目录 总结 刷题 2018 - 9 - 24 2018 - 9 - 25 2018 - 9 - 26 2018 - 9 - 27 2018 - 9 - 28 2018 - 9 - 29 2018 - ...

  5. cf1088D Ehab and another another xor problem (构造)

    题意:有两数a,b,每次你可以给定c,d询问a xor c和b xor d的大小关系,最多询问62次($a,b<=2^{30}$),问a和b 考虑从高位往低位做,正在做第i位,已经知道了a和b的 ...

  6. bzoj2555(后缀自动机+LCT)

    题目描述 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 题解 做法很自然,建出后缀自动机,维护每个节点的right ...

  7. 【Linux】linux中文本操作利器grep,awk,sed

    grep命令 grep(global search regular expression)是一种强大的文本搜索工具,它可以使用正则表达式搜索文本,并把匹配的行打印出来.平时搜索文本中内容的时候是非常方 ...

  8. 20165223《Java程序设计》第九周Java学习总结

    教材学习内容总结 第13章- URL类 InetAddress类 套接字 UDP数据报 广播数据报 Java远程调用(RMI) 教材学习中的问题和解决过程 1. URL类 URL类构造方法: 使用字符 ...

  9. Docker中如何删除image(镜像)

    原文地址:http://yaxin-cn.github.io/Docker/how-to-delete-a-docker-image.html docker中删除images的命令是docker rm ...

  10. Arch更新时failed to prepare transaction

    error: failed to prepare transaction (could not satisfy dependencies) :: ffmpeg2.8: installing x265 ...