zoukankan      html  css  js  c++  java
  • luogu1993 小K的农场

    题目大意

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

    • 农场a比农场b至少多种植了c个单位的作物,
    • 农场a比农场b至多多种植了c个单位的作物,
    • 农场a与农场b种植的作物数一样多。

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

    差分约束

    要处理一组类似$x_{i1}+k_igeq x_{i2}$的形式的偏序关系,我们发现图上每条边e连接的两个结点的单源最短路径长度都满足u[e]+w[e]>=v[e](u可能在v的最短路径上,也可能不在)。所以我们将图上的结点$x_{i1}, x_{i2}$连一条长度为$k_i$的边,将原点与所有边相连,跑一下最短路,那么每个结点的dist就是其所对应$x$值的一个解。

    无解当且仅当图中有负环,判断负环的方法可以为:在SPFA时,判断每个结点的最短路径所经过的结点的数量是否超过TotNode,超过了则说明有负环。

    题解说明

    使用STL里的queue维护Node*,在BZOJ上可以AC,在洛谷上由于评测机64位指针8子节导致RE;queue改为维护int原先RE变为TLE,开O2后AC,不开O2即使手写queue也没有卵用。据说有用Dfs实现的SPFA,但是我不会。

    // luogu-judger-enable-o2
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    
    const int MAX_NODE = 10010, MAX_EDGE = MAX_NODE * 3, INF = 0x3f3f3f3f;
    
    struct Node;
    struct Edge;
    
    struct Node
    {
        Edge *Head;
        int Dist, FromEdgeCnt;
        bool Inq;
    }_nodes[MAX_NODE];
    int _vCount;
    
    struct Edge
    {
        Node *To;
        Edge *Next;
        int Weight;
    }_edges[MAX_EDGE];
    int _eCount;
    
    void AddEdge(int uId, int vId, int w)
    {
        Node *u = _nodes + uId, *v = _nodes + vId;
        Edge *e = _edges + ++_eCount;
        e->Weight = w;
        e->To = v;
        e->Next = u->Head;
        u->Head = e;
    }
    
    bool SPFA(Node *start)
    {
        for (int i = 1; i <= _vCount; i++)
            _nodes[i].Dist = INF;
        start->Dist = 0;
        start->FromEdgeCnt = 0;
        start->Inq = true;
        static queue<int> q;
        q.push(start - _nodes);
        while (!q.empty())
        {
            int curId = q.front();
            q.pop();
            Node *cur = _nodes + curId;
            cur->Inq = false;
            if (cur->FromEdgeCnt > _vCount)
                return false;
            for (Edge *e = cur->Head; e; e = e->Next)
            {
                if (cur->Dist + e->Weight < e->To->Dist)
                {
                    e->To->Dist = cur->Dist + e->Weight;
                    e->To->FromEdgeCnt = cur->FromEdgeCnt + 1;
                    if (!e->To->Inq)
                    {
                        e->To->Inq = true;
                        q.push(e->To - _nodes);
                    }
                }
            }
        }
        return true;
    }
    
    int main()
    {
        int qCnt;
        _eCount = 0;
        scanf("%d%d", &_vCount, &qCnt);
        _vCount++;
        for (int i = 1; i <= qCnt; i++)
        {
            int op, a, b, c;
            scanf("%d", &op);
            switch (op)
            {
            case 1:
                scanf("%d%d%d", &a, &b, &c);
                AddEdge(a, b, -c);
                break;
            case 2:
                scanf("%d%d%d", &a, &b, &c);
                AddEdge(b, a, c);
                break;
            case 3:
                scanf("%d%d", &a, &b);
                AddEdge(a, b, 0);
                AddEdge(b, a, 0);
                break;
            }
        }
        for (int i = 1; i <= _vCount - 1; i++)
            AddEdge(_vCount, i, 0);
        if (SPFA(_nodes + _vCount))
            printf("Yes
    ");
        else
            printf("No
    ");
        return 0;
    }
    

      

  • 相关阅读:
    [机器学习案例1]基于KNN手写数字识别
    Android横竖屏切换View设置不同尺寸或等比例缩放的XML解决方案
    Qt之网络编程
    Redis系列-存储篇sorted set主要操作函数小结
    Code First Migrations更新数据库结构的具体步骤
    json文件解析
    go语言文件操作
    docker容器与主机之间的文件复制
    ubuntu16.04 安装docker
    Go语言string,int,int64 ,float之间类型转换方法
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9388100.html
Copyright © 2011-2022 走看看