P1993 小K的农场 && 差分约束

首先第一篇讨论的是差分约束系统解的存在

差分约束系统是有 \(n\) 个变量及 \(m\) 个(如 \(x_{i} - x_{j} \leq a_{k}\) )关系组成的系统

差分约束解的求解可以转化为图中最短路的求解问题

对一个标准的差分约束式, 我们可以如下连边\[x_{i} - x_{j} \leq a_{k}\ \Rightarrow \ V(j\ ,\ i), w[j,i] = a[k]\]
对于一个不是那么标准的差分约数式, 我们可以做如下变形:\[x_{i} - x_{j} \geq a_{k} \Rightarrow x_{j} - x_{i} \leq -a_{k}\]\[x_{i} - x_{j} < a_{k} \Rightarrow x_{i} - x_{j} \leq a_{k} + 1\]\[x_{i} = x_{j} \Rightarrow x_{i} - x_{j} \leq 0 \ \& \&\ x_{j} - x_{i} \leq 0\]

然后连边, 转化为最短路是否有解的问题, 考虑 \(SPFA\) 解决, 值得注意的是, 这个图不一定只有一个联通块, 所以我们从源点 \(0\) 出发, 初始先像每一个点连边, 权为 \(0\) , 以源点为起点进行 \(SPFA\) 便会比较方便了

P.s : 一般差分约数只是判断是否有解的数据会比较恶心,所以可以使用 \(SPFA(dfs)\) 来代替 \(SPFA(bfs)\) , 遇到负环直接退出, 效率较高

可以试想一下, 跑出来的最短路是什么呢? 无法到达又说明着什么呢? 这将会在下一篇进行探讨

P1993 小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”。



板题, 手算, 转换一下关系连边即可。

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
int RD(){
    int flag = 1, out = 0;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 1000019, INF = 1e9 + 19;
int head[maxn], nume = 1;
int num, ni;
struct Node{
    int u, v, dis, nxt;
    }E[maxn << 3];
void add(int u, int v, int dis){
    E[++nume].nxt = head[u];
    E[nume].v = v;
    E[nume].dis = dis;
    head[u] = nume;
    }
int d[maxn];
bool ins[maxn], flag;
void SPFA(int u){
    ins[u] = 1;
    for(int i = head[u];i;i = E[i].nxt){
        int v = E[i].v, dis = E[i].dis;
        if(d[u] + dis < d[v]){
            if(ins[v]){flag = 1;return ;}
            d[v] = d[u] + dis;
            SPFA(v);
            }
        }
    ins[u] = 0;
    }
int main(){
    num = RD();ni = RD();
    for(int i = 1;i <= num;i++)add(0, i, 0);
    for(int i = 1;i <= ni;i++){
        int cmd = RD(), a = RD(), b = RD(), c;
        if(cmd == 1)c = RD(), add(a, b, -c);
        else if(cmd == 2)c = RD(), add(b, a, c);
        else add(a, b, 0), add(b, a, 0);
        }
    for(int i = 1;i <= num;i++)d[i] = INF;
    SPFA(0);
    flag ? puts("No") : puts("Yes");
    return 0;
    }

原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9346082.html

时间: 2024-10-28 15:15:52

P1993 小K的农场 && 差分约束的相关文章

BZOJ 3436: 小K的农场 差分约束

题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=3436 题解: 裸的差分约束: 1.a>=b+c  ->  b<=a-c  ->  d[v]<=d[u]+w  ->  建一条边从a到b,权值为-c 2.a<=b+c  ->  d[v]<=d[u]+w  -> 建一条边从b到a,权值为c 3.a==b  ->  d[v]<=d[u]+0&&d[u]<=d

P1993 小K的农场

P1993 小K的农场 这个题,涉及到的知识点是差分约束. 差分约束,是用来判断不等式是否有解集和求出一组特解的一种方法. 具体是使用最短(长)路算法. 观察最短路算法,有一个类似与三角形三边关系的不等式. \[dis[a]+weight>=dis[b]\] 其中a与b之间直接连了一条边权为weight的边. 通过我们熟练地水做一系列最短路,我们一眼就能看出这是正确的. 那我们再来看一个不等式\(x_1-x_2<=c\),其中\(c\)为常数 变一个型 \[x_1<=x_2+c\] \[

洛谷 P1993 小K的农场

P1993 小K的农场 题目描述 小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述: 农场a比农场b至少多种植了c个单位的作物, 农场a比农场b至多多种植了c个单位的作物, 农场a与农场b种植的作物数一样多. 但是,由于小K的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合. 输入输出格式 输入格式: 第一行包括两个整数 n 和 m,分别表示农场数目和小

P1993 小 K 的农场

P1993 小 K 的农场 题目描述 小 K 在 Minecraft 里面建立很多很多的农场,总共 n 个,以至于他自己都忘记了每个 农场中种植作物的具体数量了,他只记得一些含糊的信息(共 m 个),以下列三种形式描 述: 农场 a 比农场 b 至少多种植了 c 个单位的作物. 农场 a 比农场 b 至多多种植了 c 个单位的作物. 农场 a 与农场 b 种植的作物数一样多. 但是,由于小 K 的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种 植作物数量与他记忆中的所有信息吻合. 输

[Luogu] P1993 小K的农场

题目描述 小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述: 农场a比农场b至少多种植了c个单位的作物, 农场a比农场b至多多种植了c个单位的作物, 农场a与农场b种植的作物数一样多. 但是,由于小K的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合. 输入输出格式 输入格式: 第一行包括两个整数 n 和 m,分别表示农场数目和小 K 记忆中的信息数目.

洛谷P1993 小 K 的农场

题目描述 小 K 在 Minecraft 里面建立很多很多的农场,总共 n 个,以至于他自己都忘记了每个 农场中种植作物的具体数量了,他只记得一些含糊的信息(共 m 个),以下列三种形式描 述: 农场 a 比农场 b 至少多种植了 c 个单位的作物. 农场 a 比农场 b 至多多种植了 c 个单位的作物. 农场 a 与农场 b 种植的作物数一样多. 但是,由于小 K 的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种 植作物数量与他记忆中的所有信息吻合. 输入输出格式 输入格式: 从

洛谷P1993 小 K 的农场(查分约束)

/* 加深一下对查分约束的理解 建图的时候为了保证所有点联通 虚拟一个点 它与所有点相连 权值为0 然后跑SPFA判负环 这题好像要写dfs的SPFA 要不超时 比较懒 改了改重复进队的条件~ */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #define maxn 40010 using namespace std; int n,m,num,head[maxn

bzoj3436: 小K的农场(差分约束)

3436: 小K的农场 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1575  Solved: 690[Submit][Status][Discuss] Description 背景 小K是个特么喜欢玩MC的孩纸... 描述 小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得 一些含糊的信息(共m个),以下列三种形式描述:农场a比农场b至少多种植了c个单位的作物,农场a比农场b至多 多种植了

bzoj3436: 小K的农场(差分约束)

3436: 小K的农场 题目:传送门 题解: 查分基础: t==1  a>=b+c t==2  b>=a-c t==3  a>=b+0 b>=a+0 跑最长路一A 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 int