据说差分约束有很多种,但是我学过的只有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. hdu—3861(tarjan+二分图)

    题意:给你n个城市,每个城市之间有一条有向边,将城市划分为几个区域,问你最小的划分方法, 划分规则为:能相互到达的放在一个区域:然后区域内的a,b两点肯定存在某种方式,使得a能到b或者b能到a(注意, ...

  2. JarvisOJ Basic 熟悉的声音

    两种元素,还有声音,想到了莫尔斯电码,解码得到 jbluwewnz 提交,发现不对,觉得应该是有实际意义的东西,实在想不到还能怎么解,就去看了题解. 发现这个还可以再套一个凯撒密码,就拿python写 ...

  3. IDEA下载依赖时提示 resolving dependencies of xxx, yyy

    IDEA下载依赖时提示 resolving dependencies of xxx, yyy ,卡住不动 使用Maven命令可以更清楚地分析问题,在IDEA命令行窗口执行mvn compile命令,提 ...

  4. Android Studio 显示 logcat

    首先调出 logcat,在整个android studio的左下角(藏的好,尼玛.) 接着设置下面三个红框 1 选择你自己的模拟器. 2 选择Warm 3 选择not filter

  5. Java实现月份递减

    问题:从当前月份开始,往前3年的所有月份 返回map类型,key是String,value是Date,map倒序排列 public static Map<String, Date> get ...

  6. 【题解】 bzoj2982: combination (Lucas定理)

    题面戳我 Solution 板子题 Code //It is coded by ning_mew on 7.25 #include<bits/stdc++.h> #define LL lo ...

  7. 【JVM】查看JVM加载的类及类加载器的方法

    查看JVM加载了哪些类 java -verbose[:class|gc|jni] 在输出设备上显示虚拟机运行信息. java -verbose:class 在程序运行的时候有多少类被加载!你可以用ve ...

  8. C++ 中 const、volatile、mutable的用法

    @2019-01-14 [小记] C++中const.volatile.mutable的用法

  9. python中,下级模块引用上级模块:SystemError: Parent module '' not loaded, cannot perform relative import

    当在下级中引用上级时,使用相对导包会出错,SystemError: Parent module '' not loaded, cannot perform relative import 运行test ...

  10. 牛客寒假算法基础集训营3B 处女座的比赛资格(用拓扑排序解决DAG中的最短路)

    链接:https://ac.nowcoder.com/acm/contest/329/B 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...