美文网首页
CCF CSP 202006-5 乔乔和牛牛逛超市

CCF CSP 202006-5 乔乔和牛牛逛超市

作者: 西部小笼包 | 来源:发表于2020-08-16 13:56 被阅读0次

【题目描述】 乔乔和牛牛去逛超市了,超市里有 n 种商品,他们决定买一些商品回家。但是,第i 种商品一旦被选择,购买的个数就必须是 Li 和 Ri 之间的整数(含端点)。某些商品之间有依赖关系,依赖关系有两种:
• 1. 只有第 x 种商品被购买了,第 y 种商品才可以被购买。

• 2. 只有第 x 种商品被购买了,第 y 种商品的购买个数才可以恰好是 Lx 或 Rx 。

购买一个商品的带来的开心程度和这个商品购买的个数有关,若第 i 个商品购买了x 个 x > 0 ,则收益为 ai * x * x + bi * x + ci ,否则为 0 。

现在牛牛和乔乔想知道逛超市的最大总开心程度是多少,你能帮他们选购商品并确定购买商品数量吗?

【输入格式】
从标准输入读入数据。

第一行包含两个整数 n ,m ,表示商品数量和依赖关系数量。0 ≤ n ≤ 10^4,0 ≤ m ≤ 10^5。

接下来 n 行,每行包含五个整数 Li,Ri,ai,bi,ci ,描述一个商品。1 ≤ Li ≤ Ri ≤104,−5 ≤ a ≤ 5,−104 ≤ bi,ci ≤ 104, Li + 1 ≤ Ri − 1 。

接下来 m 行,每行包含三个整数 z, x,y ,表示第 x 种商品对第 y 种商品存在第 z种关系。1 ≤ x,y ≤ n,1 ≤ z ≤ 2。

【输出格式】
输出到标准输出。
输出一个整数,表示最大总开心程度。

image.png

【样例1 输出】

231

破题思路

  1. 有一组商品,选择有依赖关系,每个点有一个权值。我们要选择任意多种使得权值最大,这个是一个最大权闭合子图模型。

  2. 所谓闭合子图,就是在一个有向图中,我们选一组点集,使得这个点的集合,里的所有出边,都在这个点集内部。又称肥水不流外人田。
    因为一个点集不能有出边。我们要保证依赖关系。就是先选的要是被指的。比如选课,要先选语言课,完成了语言课的才能去选程设课。那么要从程设课向语言课指一条边。
    那么闭合子图的没有出边就能保证,不会有需要先选的没选,而选了又依赖的东西。

  3. 本来每个物品就是一个点,这个点的权值,我们可以基于二次函数求范围内的最大值贪心到它的权值。但是这题有2种依赖关系,所以我们可以运用拆点的思想。每个物品我们拆成2种。一种是可以买但是不能买边界,另一种是在可以买的基础上还能买边界。

  4. 所有买边界的要依赖于可以买的。也就是必须先选可以买,才能选买边界。

  5. 针对可以买,我们要计算二次函数里【L+1, R-1】的最大值。 针对买边界就是二次函数取L还是取R的最大值。

  6. 这2类点要求是互斥的,也就是说如果用了买边界,我们不能把买当中的第一类点的权值再算进去。所以我们构建第二类的点,需要用它的最大值减去第一类点的最大值。这样点集里包含第一类点代表买当中,如果2个都包含,代表买边界。

  7. 余下的就是最大权闭合子图的模板了。所有源点向所有正权点建边。负权点向汇点建边。内部边的容量都为无穷大。随后跑DINIC算法求最大流等价于最小割。然后用所有正权点的和减去最小割的值就是答案。

  8. 这道题写完提交直接就AC还是很爽的。大家加油!

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Main m = new Main();
        System.out.println(m.solve());
    }
    // 下面这组变量是DINIC跑最大流的基础变量。n是点数,m是边数
    int N = 20020, M = 300010, inf = (int) 1e9;
    // h e ne 3个数组 是数组模拟邻接表的建图方式,加边函数参加ADD
    // w 代表 残留网络的剩余容量。 d 是对所有点建立分层图,维护层数
    // cur 是当前层优化的数组 S代表源点 T代表汇点
    int[] h = new int[N], cur = new int[N], d = new int[N]; 
    int[] e = new int[M], ne = new int[M], w = new int[M];
    int S, T, idx = 0;
    
    int[][] goods;
    void add(int a, int b, int c) {
        e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++;
        e[idx] = a; w[idx] = 0; ne[idx] = h[b]; h[b] = idx++;
    }
    private long solve() {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt();
        goods = new int[n+1][];
        S = 0; T = 2 * n + 1;
        Arrays.fill(h, -1);
        
        long tot = 0; // 存所有正权点的和
        for (int i = 1; i <= n; i++) {
            goods[i] = new int[]{sc.nextInt(), sc.nextInt(),sc.nextInt(),sc.nextInt(),sc.nextInt()};
            int v1 = cal(goods[i]), v2 = cal2(goods[i]) - v1;
            // i + n 是第二类点,i是第一类点
            add(i + n, i, inf);
            tot += Math.max(0, v1) + Math.max(0, v2);
            if (v1 > 0) add(S, i, v1);
            else if (v1 < 0) add(i, T, -v1);

            if (v2 > 0) add(S, i+n, v2);
            else if (v2 < 0) add(i+n, T, -v2);
        }

        for (int i = 0; i < m; i++) {
            int type = sc.nextInt(), x = sc.nextInt(), y = sc.nextInt(), yy = y + n;
            if (type == 1) {
                add(y, x, inf);
            } else {
                add(yy, x, inf);
            }
        }
        
        // 正权和-最小割 为 最大闭合子图的解
        return tot - dinic();
    }

    // dinic 模板
    private long dinic() {
        long r = 0, flow;
        while (bfs()) while ((flow = find(S, inf)) != 0) r += flow;
        return r;
    }
    // dinic find 函数模板,带当前层优化
    private int find(int u, int limit) {
        if (u == T) return limit;
        int flow = 0;
        for (int i = cur[u]; i != -1 && flow < limit; i = ne[i]) {
            int j = e[i];
            cur[u] = i;
            if (d[j] == d[u] + 1 && w[i] > 0) {
                int v = find(j, Math.min(w[i], limit - flow));
                if (v == 0) d[j] = -1;
                w[i] -= v; w[i ^ 1] += v; flow += v;
            }
        }
        return flow;
    }

    // dinic bfs 建分层图模板
    private boolean bfs() {
        Arrays.fill(d, -1);
        cur = h.clone();
        Queue<Integer> q = new LinkedList<>();
        q.offer(S); d[S] = 0;
        while (!q.isEmpty()) {
            int a = q.poll();
            for (int i = h[a]; i != -1; i = ne[i]) {
                int b = e[i];
                if (d[b] == -1 && w[i] > 0) {
                    d[b] = d[a] + 1;
                    if (b == T) return true;
                    q.offer(b);
                }
            }
        }
        return false;
    }

    // 二次函数求值
    int y(int a, int b, int c, int x) {
        return a * x * x + b * x + c;
    }
    // 第二类点求最大值
    private int cal2(int[] g) {
        return Math.max(y(g[2],g[3],g[4],g[0]), y(g[2],g[3],g[4],g[1]));
    }
    // 第一类点求最大值
    private int cal(int[] g) {
        int a = g[2], b = g[3], c = g[4], l = g[0], r = g[1];
        if (l + 1 > r - 1) return 0;
        if (a > 0) return Math.max(y(a,b,c,l+1), y(a,b,c,r-1));
        else if (a < 0) {
            double maxX = -b / 2.0 / a;
            if (maxX <= l) return y(a, b, c, l + 1);
            else if (maxX >= r) return y(a, b, c, r - 1);
            return Math.max(y(a, b, c, (int)Math.floor(maxX)), y(a, b, c, (int)Math.ceil(maxX)));
        }
        return y(a, b, c, b > 0 ? r - 1 : l + 1);
    }
}

相关文章

  • CCF CSP 202006-5 乔乔和牛牛逛超市

    【题目描述】 乔乔和牛牛去逛超市了,超市里有 n 种商品,他们决定买一些商品回家。但是,第i 种商品一旦被选择,购...

  • CCF 通信网络

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 20170...

  • 徐州CCF CSP-J/S2020第二轮提高级获奖名单 一等2人

    CCF CSP-J/S2020第二轮提高级一等名单 证书编号 省份 准考证号 姓名 性别 总分 学校 年级 CCF...

  • CCF/CSP 公共钥匙盒

    无情的copy机器...【解题思路】:排序+模拟【代码如下】:

  • 我的CSP2019-J游记

    基础信息: 省份:北京 学校:【数据删除】 年级:初一 比赛:2019 年 CCF 非专业级软件能力认证(CSP-...

  • 聊聊算法比赛

    先说说线下的比赛,说到线下的比赛首先想到的绝对是ccf系列(csp,noi啥的)和acm系列。但我认为这两种比赛都...

  • 什么编程比赛适合初学者

    先说说线下的比赛,说到线下的比赛首先想到的绝对是ccf系列(csp,noi啥的)和acm系列。但我认为这两种比赛都...

  • CSP2020-S 组游记

    基本信息 省份:北京 学校:【QAQ】 年级:初二 比赛:2020 年 CCF 非专业级软件能力认证(CSP-J/...

  • CSP第二题思路总结

    CCF-CSP考试的时候总是会犯一些错误,并且自己思路太单调想不到好方法,这里简单总结一下相关的方法和技巧。 1、...

  • 和妈妈逛超市

    今天下午,妈妈说要去超市买东西,就带着我去了,到了那里,我帮妈妈拿了一个小车,妈妈在前面选,我帮妈妈推车,妈妈买了...

网友评论

      本文标题:CCF CSP 202006-5 乔乔和牛牛逛超市

      本文链接:https://www.haomeiwen.com/subject/itmtjktx.html