zoukankan      html  css  js  c++  java
  • ZOJ1508 Intervals 差分约束

    题意:给定若干个连续的整数区间[ai, bi]以及ci,现在要求这样一个集合Z,集合Z中的元素与每个给定的区间的元素交集至少有ci个。

    解法:通过把dis[i]看做Z中小于等于整数i一共有多少个元素。那么对于题目给定条件有表达式dis[b] - dis[a-1] >= ci,根据这个不等式就能够进行构边了。除此之外,还有一些隐含的条件:0 <= dis[i]-dis[i-1] <= 1,对这些关系同样进行构边。然后要求的值就是dis[Max] - dis[Min-1] >= M中的M,其中Max和Min是出现的最小左、右边界,令dis[Max] = 0,那么就是求解的就是从Max到Min-1的最短路的相反数。

    这里解释下为什么是从Max到Min-1的最短路,由于有dis[Max]-dis[Min-1]>=M恒成立时,而M同样是一个变量,因此要大于M就要大于M的最大值,因此问题转化为这个不等式中如何求解M的最大值,通过对式子的转化就为dis[Min-1]-dis[Max]<=-M,也就是求-M的最小值,而这个-M在途中最小就是Min-1到Max的最短路了,否则dis[Min-1]就会被dis[Max]-M代替了。

    代码如下:

    #include <cstdlib>
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    int N, idx, head[50005];
    int Min, Max;
    
    // 设对图求出最短路表示的信息dis[i]表示Z集合中包含有多少个小于i的数 
    struct Edge {
        int v, ct, next;
    }e[160000];
    
    void insert(int a, int b, int ct) {
        e[idx].v = b, e[idx].ct = ct;
        e[idx].next = head[a];
        head[a] = idx++;
    }
    
    int dis[50005];
    char vis[50005];
    #include <queue>
    
    void spfa() {
        queue<int>q;
        memset(dis, 0x3f, sizeof (dis));
        memset(vis, 0, sizeof (vis));
        q.push(Max);
        vis[Max] = 1, dis[Max] = 0;
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            vis[v] = 0;
            int tv;
            for (int i = head[v]; i != -1; i = e[i].next) {
                if (dis[e[i].v] > dis[v] + e[i].ct) {
                    dis[e[i].v] = dis[v] + e[i].ct;
                    if (!vis[e[i].v]) {
                        q.push(e[i].v);
                        vis[e[i].v] = 1;    
                    }
                }
            }
        }
    }
    
    int main() {
        int a, b, c;
        while (scanf("%d", &N) != EOF) {
            idx = 0;
            Min = 50005, Max = 0;
            memset(head, 0xff, sizeof (head));
            for (int i = 0; i < N; ++i) {
                scanf("%d %d %d", &a, &b, &c);
                ++a, ++b; // 由于0是有效的数字,因此待会最小数减1将会出现负数 
                Min = min(Min, a);
                Max = max(Max, b);
                insert(b, a-1, -c);
            }
            for (int i = Min; i <= Max; ++i) {
                insert(i-1, i, 1);
                insert(i, i-1, 0);
            }
            spfa();
            printf("%d\n", -dis[Min-1]);
        }
        return 0;    
    }
  • 相关阅读:
    实战-rsync+inotify打造文件实时备份
    实战-Mysql5.6.36脚本编译安装及初始化
    实战-CentOS6.8配置nfs服务
    CentOS7操作系统初始化
    docker搭建 SonarQube代码质量管理平台
    ubuntu 教程
    前端图表库
    WebSSH2安装过程可实现WEB可视化管理SSH工具
    devops 自动化平台网址
    AIops 智能运维平台
  • 原文地址:https://www.cnblogs.com/Lyush/p/2957731.html
Copyright © 2011-2022 走看看