zoukankan      html  css  js  c++  java
  • 题解【洛谷P3275】[SCOI2011]糖果

    题面

    其实是裸的差分约束吧 QwQ。

    对于每一种情况分类讨论一下:

    • 如果 (X=1),则 (A=B),转换一下就变成了 (Ageq B)(Bgeq A)
    • 如果 (X=2),则 (A<B),转换一下就变成了 (Bgeq A+1)
    • 如果 (X=3),则 (Ageq B)
    • 如果 (X=4),则 (A>B),转换一下就变成了 (Ageq B+1)
    • 如果 (X=5),则 (Aleq B),转换一下就变成了 (Bgeq A)

    这里说一下差分约束最基本的建图方式:

    • 对于一个不等式 (x_1 geq x_2 + c),我们都由 (x_2)(x_1) 连一条长度为 (c) 的边。

    如何求最值呢?

    结论:如果求的是最小值,那么我们就跑一遍最长路;否则就跑一遍最短路。

    具体的方法就是对于每一个 (x_i geq c) 的条件,建立一个超级源点 (0),由 (0)(x_i) 连一条长度为 (c) 的边。

    因为本题中要求每个小朋友都要分到糖果,所以我们就建立一个超级源点 (0),向每一个点连一条长度是 (1) 的边。

    最后跑一遍最长路就可以了。

    注意如果图中有正环就说明无解。

    而且这一题中用队列貌似会被卡,因此我们在找正环时把栈改成队列即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    
    const int N = 100003, M = 300003;
    
    int n, m;
    int cnt[N];
    int tot, head[N], ver[M], nxt[M], edge[M];
    bool st[N];
    LL dist[N];
    int stk[N];
    
    inline void add(int u, int v, int w)
    {
        ver[++tot] = v, edge[tot] = w, nxt[tot] = head[u], head[u] = tot;
    }
    
    inline bool SPFA()
    {
        memset(cnt, 0, sizeof cnt);
        memset(st, false, sizeof st);
        memset(dist, 0xcf, sizeof dist);
        dist[0] = 0;
        int hh = 0, tt = 1;
        stk[0] = 0;
        while (hh != tt)
        {
            int u = stk[--tt];
            st[u] = false;
            for (int i = head[u]; i; i = nxt[i])
            {
                int v = ver[i], w = edge[i];
                if (dist[v] < dist[u] + w)
                {
                    dist[v] = dist[u] + w;
                    cnt[v] = cnt[u] + 1;
                    if (cnt[v] >= n + 1) return true;
                    if (!st[v])
                    {
                        st[v] = true;
                        stk[tt++] = v;
                    }
                }
            }
        }
        return false;
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; i+=1)
        {
            int x, a, b;
            scanf("%d%d%d", &x, &a, &b);
            if (x == 1) add(b, a, 0), add(a, b, 0);
            else if (x == 2) add(a, b, 1);
            else if (x == 3) add(b, a, 0);
            else if (x == 4) add(b, a, 1);
            else add(a, b, 0);
        }
        for (int i = 1; i <= n; i+=1) add(0, i, 1);
        if (SPFA()) puts("-1");
        else 
        {
            LL ans = 0;
            for (int i = 1; i <= n; i+=1)
                ans += dist[i];
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Node.js 常用工具 util
    jQuery 选择器
    Node.js 创建HTTP服务器
    Node.js GET/POST请求
    JavaScript 用法
    Node.js 事件
    Node.js 函数
    Bootstrap<基础二> 网格系统
    读文章《Flexbox详解》笔记
    好文要读
  • 原文地址:https://www.cnblogs.com/xsl19/p/12409282.html
Copyright © 2011-2022 走看看