zoukankan      html  css  js  c++  java
  • POJ 3686 *最小费用流-转化成普通指派问题)

    题意】

    有N个订单和M个机器,给出第i个订单在第j个机器完成的时间Mij,每台机器同一时刻只能处理一个订单,机器必须完整地完成一个订单后才能接着完成下一个订单。问N个订单完成时间的平均值最少为多少。

    分析 :

    最小费用最大流
    如果每个工厂只能完成一个订单的话,那就是指派问题了。跑一遍最小费用流即可。但是题目每个工厂可能完成多个。
    所以需要将其拆点使得每个工厂只能完成一个订单,进而转换成指派问题。对一个工厂来说,如果每个订单都在这个
    工厂完成的话,那么时间为T=t1 + (t1+t2) + (t1+t2+t3) +... = n*t1 + (n-1)*t2 + (n-2)*t3 + ...就可将其看成
    是n个只能完成一个订单的工厂只不过它们需要乘于花费的1到N倍。

    #include <iostream>
    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
     
    using namespace std;
    const int maxn = 3000;
    const int INF = 0x3f3f3f3f;
     
    typedef pair<int,int> P;
    struct Edge
    {
        int to, cap, cost, rev;
        Edge(int to_, int cap_, int cost_, int rev_):to(to_),cap(cap_),cost(cost_),rev(rev_){}
    };
     
    vector<Edge> G[maxn];
    int V, n, m, relation[55][55];
    int h[maxn], dist[maxn], prevv[maxn], preve[maxn];
     
    void add_edge(int from, int to, int cap, int cost)
    {
        G[from].push_back(Edge(to, cap, cost, G[to].size()));
        G[to].push_back(Edge(from, 0, -cost, G[from].size()-1));
    }
     
    int min_cost_flow(int s, int t, int f)
    {
        int res = 0;
        memset(h, 0, sizeof(h));
        while(f > 0) {
            priority_queue<P, vector<P>, greater<P> > pq;
            fill(dist, dist + V, INF);
            dist[s] = 0;
            pq.push(P(0, s));
            while(!pq.empty()) {
                P p = pq.top(); pq.pop();
                int v = p.second;
                if(dist[v] < p.first)   continue;
                for(int i = 0; i < G[v].size(); i++) {
                    Edge& e = G[v][i];
                    if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                        dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        pq.push(P(dist[e.to], e.to));
                    }
                }
            }
            if(dist[t] == INF)  return -1;
     
            for(int v = 0; v < V; v++)  h[v] += dist[v];
     
            int d = f;
            for(int v = t; v != s; v = prevv[v]) {
                d = min(d, G[prevv[v]][preve[v]].cap);
            }
            f -= d;
            res += d * h[t];
            for(int v = t; v != s; v = prevv[v]) {
                Edge& e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return res;
    }
     
    int main()
    {
        //freopen("in.txt", "r", stdin);
        int T;
        scanf("%d", &T);    getchar();
        while(T--) {
            scanf("%d%d", &n, &m);
            for(int i = 0; i < maxn; i++)   G[i].clear();
     
            for(int i = 0; i < n; i++) {
                for(int j = 0; j < m; j++) {
                    scanf("%d", &relation[i][j]);
                }
            }
     
            int s = n + n * m, t = s + 1;
            for(int j = 0; j < m; j++) {//工厂
                for(int k = 0; k < n; k++) {//将工厂拆成n个点
                    add_edge(n + j * n + k, t, 1, 0);
                    for(int i = 0; i < n; i++) {
                        add_edge(i, n + j * n + k, 1, (k + 1) * relation[i][j]);
                    }
                }
            }
            for(int i = 0; i < n; i++)  add_edge(s, i, 1, 0);
            V = t + 1;
            printf("%.6f
    ", (double)min_cost_flow(s, t, n) / n);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    有效管理时间的十八种方法
    针对某个块下面的按钮注册点击事件
    vs2015运行项目时出现“编译器失败,错误代码为 1”的解决方案
    淘宝API调用 申请 获取session key
    中小型研发团队架构实践:生产环境诊断利器WinDbg帮你快速分析异常情况Dump文件
    中小型研发团队架构实践:如何规范公司所有应用分层?
    中小型研发团队架构实践:电商如何做企业总体架构?
    中小型研发团队架构实践:高效率、低风险,一键发布并测试的持续集成工具Jenkins
    ASP.NET全栈开发验证模块之在Vue中使用前端校验
    计算机基础存储结构
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9327539.html
Copyright © 2011-2022 走看看