zoukankan      html  css  js  c++  java
  • 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[v]+0 建一条边从a到b,权值为0。建一条边从b到a,权值为0.

    建完图,从原点0到各点连边,权值都为0,跑最短路。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<queue>
    #define mp make_pair
    #define X first
    #define Y second
    using namespace std;
    
    const int maxn = 10000 + 10;
    
    vector<pair<int,int> > G[maxn];
    
    int n, m;
    
    int inq[maxn], d[maxn], cnt[maxn];
    bool spfa(int s) {
        memset(inq, 0, sizeof(inq));
        memset(d, 0x7f, sizeof(d));
        memset(cnt, 0, sizeof(cnt));
        queue<int> Q;
        d[s] = 0, inq[s] = 1, Q.push(s);
        while (!Q.empty()) {
            int u = Q.front(); Q.pop();
            inq[u] = 0;
            for (int i = 0; i < G[u].size(); i++) {
                int v = G[u][i].X,w=G[u][i].Y;
                if (d[v] > d[u] + w) {
                    d[v] = d[u] + w;
                    if (!inq[v]) {
                        inq[v] = 1, Q.push(v);
                        if (++cnt[v] > n + 1) return false;
                    }
                }
            }
        }
        return true;
    }
    
    void init() {
        for (int i = 0; i <= n; i++) G[i].clear();
    }
    
    int main() {
        while (scanf("%d%d", &n, &m) == 2 && n) {
            init();
            for (int i = 1; i <= n; i++) {
                G[0].push_back(mp(i, 0));
            }
            for (int i = 0; i < m; i++) {
                int cmd, a, b,c;
                scanf("%d", &cmd);
                if (cmd == 1) {
                    scanf("%d%d%d", &a, &b, &c);
                    G[a].push_back(mp(b, -c));
                }
                else if (cmd == 2) {
                    scanf("%d%d%d", &a, &b, &c);
                    G[b].push_back(mp(a, c));
                }
                else {
                    scanf("%d%d", &a, &b);
                    G[a].push_back(mp(b, 0));
                    G[b].push_back(mp(a, 0));
                }
            }
            bool ans = spfa(0);
            if (ans) puts("Yes");
            else puts("No");
        }
        
        return 0;
    }
    
    /*
    3 3
    3 1 2
    1 1 3 1
    2 2 3 2
    */
  • 相关阅读:
    C++模板学习之优先队列实现
    static 和const分别怎么用,类里面static和const可以同时修饰成员函数吗?
    C和C++的区别
    C++多态例子_虚函数
    转:master公式(主方法)
    C++11最常用的新特性如下
    转:哈夫曼树详解
    linux shell脚本
    linux 正则表达式
    linux shell命令
  • 原文地址:https://www.cnblogs.com/fenice/p/5617012.html
Copyright © 2011-2022 走看看