区间.java 2.7 KB
Newer Older
qq_36480062's avatar
c  
qq_36480062 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
package graph.差分约束;

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Scanner;

/**
 * https://blog.csdn.net/qq_44828887/article/details/107272314
 * 给定n个区间,[ai,bi]和n个整数Ci
 * 你需要构造一个整数集合 Z,
 * 使得∀i∈[1,n],Z 中满足ai≤x≤bi的整数 x 不少于 ci 个。
 * 求这样的整数集合 Z 最少包含多少个数。
 * 1≤n≤50000,
 * 0≤ai,bi≤50000,
 * 1≤ci≤bi−ai+1
 * 输入样例:
 * 5
 * 3 7 3
 * 8 10 3
 * 6 8 1
 * 1 3 1
 * 10 11 1
 * 输出样例:
 * 6
 * 该题必定有解,显然全放进去,一定满足要求
 * 思路:
 * 先将不等式写出来
 * 将所有区间向右移一位,这样如果1-2有一条边 3-4有一条边,
 * 我们应该让他可以处理为1-4区间,
 * 所以相当于给的区间为左闭右闭的区间改为左闭右开的区间。
 * 初始的时候建立向右走1权值为0的边,向左走1权值为-1的边。
 * 跑最长路即可。
 * 列不等式:
 * S0=0
 * Si表示1~i中被选出的数的个数
 * S5001的最小值,用最长路求解
 * Si>=S(i-1)  1<=i<=50001
 * Si-S(i-1)<=1  =>S(i-1)>=Si-1
 * [a,b]区间选c个,也就是Sb-S(a-1)>=c
 * 不等关系要找全
 */
public class 区间 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1; i <= 50001; i++) {
            add(i - 1, i, 0);
            add(i, i - 1, -1);
        }
        int a, b, c;
        while (n-- != 0) {
            a = sc.nextInt();
            b = sc.nextInt();
            c = sc.nextInt();
            a++;
            b++;
            add(a - 1, b, c);
        }
        spfa();
        System.out.println(dis[50001]);
    }

    private static void spfa() {
        q.add(0);
        Arrays.fill(dis, -Integer.MAX_VALUE / 2);
        st[0] = true;
        dis[0] = 0;
        while (!q.isEmpty()) {
            int t = q.poll();
            st[t] = false;
            for (int i = h[t]; i != 0; i = ne[i]) {
                int j = e[i];
                if (dis[j] < dis[t] + w[i]) {
                    dis[j] = dis[t] + w[i];
                    if (!st[j]) {
                        q.add(j);
                        st[j] = true;
                    }
                }
            }
        }
    }


    static int n, m, N = 50010, M = 150010, count = 1;
    static int[] h = new int[N];
    static int[] e = new int[M];
    static int[] ne = new int[M];
    static int[] w = new int[M];
    static int[] dis = new int[N];
    static boolean[] st = new boolean[N];
    static ArrayDeque<Integer> q = new ArrayDeque<Integer>();

    static void add(int a, int b, int c) {
        e[count] = b;
        w[count] = c;
        ne[count] = h[a];
        h[a] = count++;
    }
}