小K的农场 洛谷1993 差分约束

题目描述


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

农场 a 比农场 b 至少多种植了 c 个单位的作物。

农场 a 比农场 b 至多多种植了 c 个单位的作物。

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

输入格式:


从 farm.in 中输入数据

第一行包括两个整数 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 一样多。

输出格式:


输出到 farm.out 中

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

说明


对于 100% 的数据保证:1 ≤ n,m,a,b,c ≤ 10000。

题解


一眼题,差分约束+spfa判环
注意这里spfa要用stack提高判断环的效率,为了保证图的连通我们由原点连每一个点权为0,这一步倒着做不然会T

Code


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#define debug puts("-----")
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)
#define fill(x, t) memset(x, t, sizeof(x))
#define min(x, y) x<y?x:y
#define max(x, y) x>y?x:y
#define PI (acos(-1.0))
#define EPS (1e-8)
#define INF (1<<30)
#define ll long long
#define db double
#define ld long double
#define N 10001
#define E N * 16 + 1
#define MOD 100000007
#define L 255
using namespace std;
struct edge{
    int x, y, w, next;
}e[E];
int inQueue[N], dis[N], cnt[N], ls[N];
inline int read(){
    int x = 0, v = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-'){
            v = -1;
        }
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0'){
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return x * v;
}
inline int addEdge(int &cnt, const int &x, const int &y, const int &w = 1){
    e[++ cnt] = (edge){x, y, w, ls[x]}; ls[x] = cnt;
    return 0;
}
inline int spfa(const int &st, const int &ed, const int &n){
    fill(dis, 63);
    dis[st] = 0;
    fill(inQueue, 0);
    inQueue[st] = 1;
    fill(cnt, 0);
    stack<int>q;
    q.push(st);
    while (!q.empty()){
        int now = q.top(); q.pop();
        // printf("%d \n", now);
        if (++ cnt[now] >= n){
            return 0;
        }
        for (int i = ls[now]; i; i = e[i].next){
            if (dis[now] + e[i].w < dis[e[i].y]){
                dis[e[i].y] = dis[now] + e[i].w;
                if (!inQueue[e[i].y]){
                    inQueue[e[i].y] = 1;
                    q.push(e[i].y);
                }
            }
        }
        inQueue[now] = 0;
    }
    return 1;
}
int main(void){
    int n = read(), m = read();
    int edgeCnt = 0;
    rep(i, 1, m){
        int opt = read(), x = read(), y = read(), w = 0;
        if (opt != 3){  
            w = read();
        }
        switch (opt){
            case 1:{addEdge(edgeCnt, x, y, -w); break;}
            case 2:{addEdge(edgeCnt, y, x, w); break;}
            case 3:{addEdge(edgeCnt, x, y, 0); addEdge(edgeCnt, y, x, 0); break;}
        }
    }
    drp(i, n, 1){
        addEdge(edgeCnt, 0, i, 0);
    }
    int ans = spfa(0, n, n);
    if (ans != 0){
        printf("Yes\n");
    }else{
        printf("No\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值