• 2013 Asia Hangzhou Regional Contest hdu4780 Candy Factory


    参考:https://blog.csdn.net/sd_invol/article/details/15813671

    要点

    1. 每个任务的结束时间是固定的,不受任何因素影响
    2. 机器只在最一开始有用,在那之后都是任务之间的转换

    连边

    将任务拆点,入点 i, 出点 i', 连边 (i, i' [1,1], 0)

    设源点 s_, 汇点 t_

    1. 对于机器 (i (i in [1, m])), 连 (s_, i, 1, 0),即流量为1,费用为0
      1. 对每个任务 (j)
        • 如果 (C[i][j] le ss[i]),连 (i, j, 1, D[i][j])
        • 否则如果 (C[i][j] < tt[j]),连 (i, j, 1, D[i][j] + k*(C[i][j] - s[j]))
        • 否则不连边
    2. 对于每个任务 (i(iin[1,n])),
      1. 连 (i, i', [1,1],0), 即流量在 [1,1]范围内,费用为0的边
      2. 连 (i',t_, 1, 0)
      3. 对于另一个任务 j,考虑 i -> j 的转换, 即 (endTime = tt[i] + E[i][j])
        • 如果 (endTime le ss[j]), 连(i', j, 1, F[i][j])
        • 否则如果 (endTime lt tt[j]) ,连 (i', j, 1, F[i][j] + k * (endTime - ss[j]))
        • 否则不连边

    然后对该网络求有源汇的上下界网络流即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    #define dbg(x...) do { cout << "33[32;1m" << #x <<" -> "; err(x); } while (0)
    void err() { cout << "33[39;0m" << endl; }
    template<class T, class... Ts> void err(const T& arg,const Ts&... args) { cout << arg << " "; err(args...); }
    const int N = 300 + 10;
    const int M = 200010;
    int n, m, k, s_, t_, s, t;
    int ss[N], tt[N];
    int C[N][N], D[N][N], E[N][N], F[N][N];
    int head[N], nxt[M], ver[M], edge[M], cost[M], tot;
    int d[N], v[N], incf[N], pre[N];
    int ans, maxflow;
    void add(int x, int y, int z, int c){
        ver[++tot] = y, edge[tot] = z, nxt[tot] = head[x], head[x] = tot, cost[tot] = c;
        ver[++tot] = x, edge[tot] = 0, nxt[tot] = head[y], head[y] = tot, cost[tot] = -c;
    }
    bool spfa(){
        queue<int> q;
        memset(d, 0x3f, sizeof d);
        memset(v, 0, sizeof v);
        q.push(s);
        d[s] = 0, v[s] = 1;
        incf[s] = inf;
        while(q.size()){
            int x = q.front();
            q.pop();
            v[x] = 0;
            for (int i = head[x]; i;i=nxt[i]){
                if(!edge[i])
                    continue;
                int y = ver[i];
                if(d[y] > d[x] + cost[i]){
                    d[y] = d[x] + cost[i];
                    incf[y] = min(incf[x], edge[i]);
                    pre[y] = i;
                    if(!v[y])
                        v[y] = 1, q.push(y);
                }
            }
        }
        if(d[t] == inf)
            return false;
        return true;
    }
    
    void update(){
        int x = t;
        while(x != s){
            int i = pre[x];
            edge[i] -= incf[t];
            edge[i ^ 1] += incf[t];
            x = ver[i ^ 1];
        }
        maxflow += incf[t];
        ans += d[t] * incf[t];
    }
    
    
    int main(){
        while(~scanf("%d%d%d", &n, &m, &k)){
            if(n == 0 && m == 0 && k == 0)break;
            tot = 1;
            s_ = n + n + m + 1, t_ = s_ + 1, s = t_ + 1, t = s + 1;
            for(int i=1;i<=t;i++) head[i] = 0;
            ans = 0, maxflow = 0;
            for(int i=1;i<=n;i++) scanf("%d%d", &ss[i], &tt[i]);
            for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d", &C[j][i]);
            for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d", &D[j][i]);
            for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d", &E[i][j]);
            for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d", &F[i][j]);
            
            // (i, i+n, [1,1], 0)
            // s 向 出点 (s, i+n, 1, 0)
            // 入点 向 t (i, t, 1, 0)
            // 出点向t_ (i+n, t_, 1, 0)
            for(int i=1;i<=n;i++){
                add(s, i+n, 1, 0);
                add(i, t, 1, 0);
                add(i+n, t_, 1, 0);
            }
            // s_-> 机器连边 流量1, 费用0
            for(int i=1;i<=m;i++){
                add(s_, n+n+i, 1, 0);
            }
            // 机器与任务连边
            for(int i=1;i<=m;i++){
                int id = 2 * n + i;
                for(int j=1;j<=n;j++){
                    if(C[i][j] <= ss[j]){ //在ss[j]之前就可以准备好
                        add(id, j, 1, D[i][j]);
                    } else if(C[i][j] < tt[j]){ // 无法在tt[j] 之前准备好
                        add(id, j, 1, D[i][j]+k*(C[i][j]-ss[j]));
                    }
                }
            }
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(i == j) continue;
                    int endTime = tt[i] + E[i][j];
                    if(endTime <= ss[j]){
                        add(i + n, j, 1, F[i][j]);
                    } else if(endTime < tt[j]) {
                        add(i + n, j, 1, F[i][j] + k * (endTime - ss[j]));
                    }
                }
            }
            add(t_, s_, inf, 0);
            while(spfa()) update();
            if(maxflow != n) puts("-1");
            else printf("%d
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    ANGRYsearch:文件快速搜索工具Ubuntu
    VMware的workstation和player有什么区别
    rclpy ros2接口
    Linux下快速搜索文件(类似Everything)
    虚拟机+Ubuntu18.04+CoppeliaSim
    PWA 技术落地!让你的站点(Web)秒变APP(应用程序)
    2021年度总结 | 葡萄城软件开发技术回顾(下)
    拉新×23,盈利可能性高出19倍,嵌入式分析到底有多香
    从服务端生成Excel电子表格(GcExcel + SpreadJS)
    当.Net撞上BI可视化,这3种“套路”你必须知道
  • 原文地址:https://www.cnblogs.com/1625--H/p/12776228.html
Copyright © 2020-2023  润新知