zoukankan      html  css  js  c++  java
  • Task Schedule

    传送门
    网络流主要还是在于如何去建图,就比如这题
    有n个任务,m个机器,每个任务有3个值,工作时间,起始时间,终止时间。
    建图思路是以s = 0为源点,t = 1001为汇点。

    最多有500天,也就是说,可以编号0位源点,[1,500]是时间节点,[501 ,1000]是任务节点,1001是汇点

    先建立源点s和各个任务之间的边,边的容量是每个任务所需要的完成的时间
    如何对任务和任务运行的时间建立边,对于一个任务,建立([s_i,e_i])这些点的边,容量为1,表示一个任务每天最多只能完成一天的任务。
    最后,建立天数和汇点t的边,容量为m,表示每天有m个机器可以工作。
    最后求出源点s到汇点t的最大流即可
    采用Dinic算法+弧优化

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define ll long long
    using namespace std;
    const int N = 1000 + 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 main(){
        int T;
        cin >> T;
        for(int tt = 1; tt <= T; tt++){
            scanf("%d%d", &m, &n);
            tot = 1; 
            ll sum = 0;
            memset(head, 0, sizeof(head));
            s = 0, t = 1001;
            for(int i = 1; i <= m; i++){
                int u, v, w;
                scanf("%d%d%d", &w, &u, &v);
                sum += w;
                add(s, 500 + i, w); add(500 + i, s, 0);
                for(int j = u; j <= v; j++){
                    add(500 + i, j, 1); add(j, 500 + i, 0);
                }
            }
            
            for(int i = 1; i <= 500; i++){
                add(i, t, n); add(t, i, 0);
            }
    
            printf("Case %d: %s
    
    ", tt, Dinic() == sum ? "Yes" : "No");
        }
        return 0; 
    }
    
  • 相关阅读:
    时装画基础知识--如何画人体
    马士兵java视频学习顺序
    Mysql 中文字符乱码问题
    zendstudio 设置默认编码 utf-8 gbk
    MYSQL 本地无ROOT权限 忘记密码
    windows 3389 远程
    windows 老掉牙CMD的命令
    mysql-常用注入渗透手法
    ubuntu 添加多个IP
    windows下简单配置apache
  • 原文地址:https://www.cnblogs.com/Emcikem/p/13259484.html
Copyright © 2011-2022 走看看