首页 > 其他分享 >NC20284 [SCOI2011]糖果

NC20284 [SCOI2011]糖果

时间:2023-01-05 19:55:06浏览次数:64  
标签:分到 int NC20284 add 小朋友 糖果 SCOI2011 dis

题目链接

题目

题目描述

幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。

输入描述

输入的第一行是两个整数N,K。
接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。
如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;
如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;
如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;
如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;
如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;

输出描述

输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。

示例1

输入

5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1

输出

11

备注

对于30%的数据,保证 \(N\leq100\)
对于100%的数据,保证 \(N\leq100000\)
对于所有的数据,保证 \(K\leq100000, 1\leq X\leq5, 1\leq A, B\leq N\)

题解

知识点:差分约束。

这是一道差分约束模板题。

求最小值用最长路。关于建边利用不等式:\(u\to v\) 权为 \(w\) ,则 \(dis[u]\geq dis[v]+w\) 。

如果存在正环,则无解。

时间复杂度 \(O(n+km)\)

空间复杂度 \(O(n+m)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int N = 100007, K = 100007;

template<class T>
struct Graph {
    struct edge {
        int v, nxt;
        T w;
    };
    int idx;
    vector<int> h;
    vector<edge> e;

    Graph(int n, int m) :idx(0), h(n + 1), e(m + 1) {}

    void add(int u, int v, T w) {
        e[++idx] = edge{ v,h[u],w };
        h[u] = idx;
    }
};
Graph <int> g(N, 3 * K);///一号坑,超级源点连边多了N个,原本边可能全是等于有2K个

int n, k;

bool vis[N];
int dis[N], cnt[N];
stack<int> q;///二号坑,queue会被卡入点顺序
bool SPFA(int s) {
    memset(dis, -1, sizeof(dis));
    q.push(s);
    dis[s] = 0;
    vis[s] = 1;
    while (!q.empty()) {
        int u = q.top();
        q.pop();
        vis[u] = 0;
        for (int i = g.h[u];i;i = g.e[i].nxt) {
            int v = g.e[i].v;
            int w = g.e[i].w;
            if (dis[v] < dis[u] + w) {
                dis[v] = dis[u] + w;
                cnt[v] = cnt[u] + 1;
                if (cnt[v] >= n + 1) return false;///三号坑,多了个超级源点,所以n+1
                if (!vis[v]) {
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
    return true;
}


int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> k;
    for (int i = 1;i <= k;i++) {
        int x, a, b;
        cin >> x >> a >> b;
        if (x == 1) {
            g.add(a, b, 0);
            g.add(b, a, 0);
        }
        else if (x == 2) {
            g.add(a, b, 1);
        }
        else if (x == 3) {
            g.add(b, a, 0);
        }
        else if (x == 4) {
            g.add(b, a, 1);
        }
        else if (x == 5) {
            g.add(a, b, 0);
        }
    }
    for (int i = 1;i <= n;i++) g.add(n + 1, i, 1);///超级源点,为了方便,距离为0,到其他点为1,表示其他点>=0+1
    /// 正边最长路用SPFA,A->B == dis[A] + w <= dis[B] 
    if (!SPFA(n + 1)) cout << -1 << '\n';
    else {
        ll ans = 0;///四号坑,最大值n^2/2
        for (int i = 1;i <= n;i++) ans += dis[i];
        cout << ans << '\n';
    }
    return 0;
}

标签:分到,int,NC20284,add,小朋友,糖果,SCOI2011,dis
From: https://www.cnblogs.com/BlankYang/p/17028735.html

相关文章

  • leetcode-575. 分糖果
    575.分糖果-力扣(Leetcode)信息:糖果的种类总个数吃一半分析:种类大于一半,那么只能吃一半种类小于一半,那么是种类量考哈希表,有点简单,熟悉Go语法还行funcdistr......
  • [JZOJ5229] 小奇的糖果
    Description有N个彩色糖果在平面上。小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果。求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的颜色。对......
  • AcWing1169. 糖果
    题目描述幼儿园里有\(N\)个小朋友,老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到......
  • 刷题笔记——3005.糖果游戏
    题目3005.糖果游戏代码li=list(map(int,input().strip().split()))lenth=len(li)foriinrange(lenth):#设置当前位置的左右位置ifi>0andi......
  • LeetCode 135.分发糖果
    LeetCode 135.分发糖果题目地址:​​https://leetcode-cn.com/problems/candy/​​题目描述:老师想给孩子们分发糖果,有N个孩子站成了一条直线,老师会根据每个孩子的表现,预......
  • 搜集糖果
     搜集糖果(candy)【题目描述】在一片N*M的四连通(一个点与它上方、下方、左方、右方这四个点连通)田野中,散布着很多很多的糖果。Ryz现在要以(x,y)为起点去搜集糖果。Ryz搜......
  • 题解 LGP7909 【[CSP-J 2021] 分糖果】
    postedon2021-10-2322:52:47|under题解|source分类讨论。一句话题意:求\(\max\limits_{i=l}^{r}\{i\bmodn\}\)首先画个数轴,按除以\(n\)向下取整的商把这些整......
  • 贪心算法简单实践 -- 分糖果、钱币找零、最多区间覆盖、哈夫曼编解码
    1.贪心算法概览贪心算法是一种算法思想。希望能够满足限制的情况下将期望值最大化。比如:Huffman编码,Dijkstra单源最短路径问题,Kruskal最小生成树等问题都希望满足限制的情......
  • 代码随想录day34 | 1005.K次取反后最大化的数组和 134.加油站 135. 分发糖果
    1005.K次取反后最大化的数组和题目|文章思路如何让翻转后的数组和最大,就是尽可能的反转绝对值大的负数。当反转次数多余时,不断反转绝对值最小的数。首先将整个数组按......
  • 135.candy 分发糖果
    问题描述135.分发糖果解题思路本题的关键在于,需要一次从前往后的遍历,第一次确定最少糖果数,同时还需要从后往前遍历,再一次确定最少糖果数。代码classSolution{publi......