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

3436: 小K的农场

>原题链接<

Description

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

Input

第一行包括两个整数n和m,分别表示农场数目和小K记忆中的信息的数目接下来m行:如果每行的第一个数是1,接
下来有三个整数a,b,c,表示农场a比农场b至少多种植了c个单位的作物如果每行第一个数是2,接下来有三个整数a
,b,c,表示农场a比农场b至多多种植了c个单位的作物如果每行第一个数是3,接下来有两个整数a,b,表示农场a
种植的数量与b一样。1<=n,m,a,b,c<=10000

Output

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

Sample Input

3 3
3 1 2
1 1 3 1
2 2 3 2

Sample Output

Yes

思路:

  看题意显然是差分约束系统,我们对1这种操作连边 y x z 代表y 比 x 少 z 对2这种连边x y -z 代表x比y少-z (就是多z) 对第三种连 x y 0 和 y x 0.然后跑一遍最长路判环即可

代码如下:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <deque>
#include <cstdlib>
using namespace std;
const int N = 23123;
int head[N], to[N], nxt[N], val[N], _;
void add(int x, int y, int z) {
    to[++_] = y;
    nxt [_] = head[x];
    head[x] = _;
    val [_] = z;
}
int vis[N], tot[N], f[N], viss[N];
deque<int> q;
int n, m;
void spfa(int s) {
    viss[s]=0;
    q.push_back(s);
    while(!q.empty()) {
        int u = q.front();
        q.pop_front();
        vis[u] = 0;
        viss[u] = 1;
        tot[u]++;
        if(tot[u]>n) {
            puts("No");
            exit(0);
        }
        for(int i=head[u];i;i=nxt[i]) {
            if(f[to[i]]<f[u]+val[i]) {
                f[to[i]]=f[u]+val[i];
                if(!vis[to[i]]) {
                    if(f[to[i]]>f[q.front()])
                    q.push_front(to[i]);
                    else q.push_back(to[i]);
                    vis[to[i]]=1;
                }
            }
        }
    }
}
int main() {
    scanf("%d%d", &n, &m);
    for(int i=1;i<=m;i++) {
        int opt;
        scanf("%d", &opt);
        if(opt==1) {
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            add(y, x, z);
        }
        else if(opt==2) {
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            add(x, y, -z);
        }
        else {
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y, 0);
            add(y, x, 0);
        }
    }
    for(int i=1;i<=n;i++) if(!viss[i])spfa(i);
    //for(int i=1;i<=n;i++) printf("%d\n", f[i]);
    puts("Yes");
}
View Code

 

转载于:https://www.cnblogs.com/Tobichi/p/9230733.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值