zoukankan      html  css  js  c++  java
  • 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
    ", f[i]);
        puts("Yes");
    }
    View Code
  • 相关阅读:
    dotnet core 获取 MacAddress 地址方法
    dotnet core 获取 MacAddress 地址方法
    dotnet core 发布只带必要的依赖文件
    dotnet core 发布只带必要的依赖文件
    Developing Universal Windows Apps 开发UWA应用 问答
    Developing Universal Windows Apps 开发UWA应用 问答
    cmd 如何跨驱动器移动文件夹
    cmd 如何跨驱动器移动文件夹
    C++ 驱动开发 error LNK2019
    C++ 驱动开发 error LNK2019
  • 原文地址:https://www.cnblogs.com/Tobichi/p/9230733.html
Copyright © 2011-2022 走看看