• kebab


    传送门
    和我上一篇博客的思路很像,区别在于每一个任务的(s_i,e_i)不一样,这题的(e_i - s_i)很大,所以无法直接全部进行建立
    那么考虑对其进行离散化,也就是或对于区间[l,r]的作为一个结点,然后按照前面的方法去建立
    对于第一层边的建立,容量就是烤肉数 * 单个烤肉的时间
    第二层边的建立,对应的应该是(times[i] - times[i - 1] * m),其中(times)数组是离散化后的时间点,那么容量是时间段 * m
    第三层边的建立,和第二层边一样

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    #define ll long long
    using namespace std;
    const int N = 2000 + 5;
    int n, m, s, t;
    struct Edge{
        int to, next, w;
    }e[N * N];
    int head[N], tot = 1, cur[N]; //弧优化
    void add(int u, int v, int w){
        e[++tot].to = v;
        e[tot].w = w;
        e[tot].next = head[u];
        head[u] = tot;
    }
    int dis[N];
    int dfs(int u, int flow){ //保证了每次DFS都能找到增广路
        if(u == t) return flow;
        int sum = 0;
        for(int i = cur[u]; i && flow > 0; i = e[i].next){
            cur[u] = i;
            int v = e[i].to, w = e[i].w;
            if(w > 0 && dis[v] == dis[u] + 1){
                int t = dfs(v, min(flow, w)); //获取这条增广路的最小流量
                e[i].w -= t; e[i ^ 1].w += t; //减去最小流量,同时反向边加上最小流量
                flow -= t; sum += t;
            }
        }
        if(!sum) dis[u] = 0;//结果u无法到达终点,或者没有增广路,切断经过这个点的路径
        return sum;
    }
    bool bfs(){//分层判断是否有增广路
        memset(dis, 0, sizeof(dis));
        queue<int> q;
        q.push(s); dis[s] = 1; cur[s] = head[s];//弧优化
        while(!q.empty()){
            int u = q.front(); q.pop();
            for(int i = head[u]; i; i = e[i].next){
                int v = e[i].to, w = e[i].w;
                if(w > 0 && !dis[v]) {
                    cur[v] = head[v];// v这个点从head[v]出发是可行的
                    dis[v] = dis[u] + 1;//分层
                    q.push(v);
                    if(v == t) return 1;//已经到达增广路,直接返回
                }
            }
        }
        return dis[t];
    }
    ll Dinic(){
        ll max_flow = 0;
        while(bfs()){
            max_flow += dfs(s, 2e9);
        }
        return max_flow;
    }
    int st[N], ed[N], num[N], ti[N], times[N], k = 0; 
    int main(){
        int n, m;
        while(~scanf("%d%d", &n, &m)){
            memset(head, 0, sizeof(head));
            tot = 1;
            k = 0;
            ll sum = 0;
            for(int i = 1; i <= n; i++){
                scanf("%d%d%d%d", &st[i], &num[i], &ed[i], &ti[i]);
                times[++k] = st[i];
                times[++k] = ed[i];
                sum += num[i] * ti[i];
            }
            sort(times + 1, times + k + 1);
            k = unique(times + 1, times + k + 1) - times;//离散化
            s = 0, t = n + k + 1;
            for(int i = 1; i <= n; i++){//第一层边
                add(s, i, num[i] * ti[i]);
                add(i, s, 0);
            }
    
            for(int i = 1; i <= n; i++){//第二层边
                for(int j = 1; j <= k; j++){
                    if(st[i] <= times[j - 1] && times[j] <= ed[i]){
                        add(i, n + j, 2e9);
                        add(n + j, i, 0);
                    }
                }
            }
            for(int i = 1; i <= k; i++){// 第三层边
                add(n + i, t, (times[i] - times[i - 1]) * m);
                add(t, n + i, 0);
            }
            printf("%s
    ", Dinic() == sum ? "Yes" : "No");
        }
        return 0; 
    }
    
    
  • 相关阅读:
    【Mysql+shell】查询结果导出到文件,文件数据导入到数据库
    【mysql】IP地址整数int和varchar的转换
    【JVM】Class结构之常量池
    【Java】Java初始化过程总结
    【转】探索 ConcurrentHashMap 高并发性的实现机制
    【并发编程】使用BlockingQueue实现<多生产者,多消费者>
    【FTP】FTP文件上传下载-支持断点续传
    【SFTP】使用Jsch实现Sftp文件下载-支持断点续传和进程监控
    【大数据】基本概念--01(转)
    【Java】Java环境变量配置
  • 原文地址:https://www.cnblogs.com/Emcikem/p/13260639.html
Copyright © 2020-2023  润新知