zoukankan      html  css  js  c++  java
  • 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; 
    }
    
    
  • 相关阅读:
    连Action Bar都不会 你能说你学过 Android?
    Java设计模式 —— 单例模式
    删库跑路 + 比特币勒索?我的MySQL被黑客攻破了
    微信小程序 带参二维码 纯Java实现
    【个人简介】关于博主&阅读指南
    微信小程序 获取 手机验证码 短信验证码 后端功能实现解析
    Handler processing failed; nested exception is java.lang.NoSuchMethodError:
    腾讯云服务器备案全流程 40天备案的血与泪
    [总结]2020年2月 OI学习/刷题记录
    [Luogu P5680][GZOI2017]共享单车
  • 原文地址:https://www.cnblogs.com/Emcikem/p/13260639.html
Copyright © 2011-2022 走看看