zoukankan      html  css  js  c++  java
  • 洛谷 P2053 :[SCOI2007]修车(拆点+最小费用流)

    https://www.luogu.org/problem/P2053

    题目描述

    同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。

    说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。

    输入格式

    第一行有两个数M,N,表示技术人员数与顾客数。

    接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。

    输出格式

    最小平均等待时间,答案精确到小数点后2位。

    输入输出样例

    输入 #1

    2 2
    
    3 2
    
    1 4

    输出 #1

    1.50

    说明/提示

    (2<=M<=9,1<=N<=60), (1<=T<=1000)

    解题思路:

    把每个工作人员拆分为n个,代表每个阶段的工人,这样一共有n*m个,源点和车费0流1, 每个阶段的工人和汇点费0流1,每个车与第i个阶段的工人的费用为 i*cost,代表如果这个工人后面有i-1个需要修理的车,需要等待的时间,求出最小费用流。

    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #define N 1020
    using namespace std;
    struct edge{
        int v;
        int w;
        int cost;
        int rev;
    };
    vector<edge>e[N];
    int n, m, prevv[N], preve[N], dis[N], inf=0x3f3f3f3f;
    
    int add(int u, int v, int w, int cost)
    {
        e[u].push_back(edge{v, w, cost, e[v].size()});
        e[v].push_back(edge{u, 0, -cost, e[u].size()-1});
    }
    int min_cost(int s, int t)
    {
        int ans=0;
        while(1)
        {
            for(int i=0; i<=t; i++)
                dis[i]=inf;
            dis[s]=0;
            bool update=true;
            while(update)
            {
                update=false;
                for(int v=0; v<=t; v++)
                {
                    if(dis[v]==inf)
                        continue;
                    for(int i=0; i<e[v].size(); i++)
                    {
                        edge &G=e[v][i];
                        if(G.w && dis[G.v]>dis[v]+G.cost)
                        {
                            dis[G.v]=dis[v]+G.cost;
                            prevv[G.v]=v;
                            preve[G.v]=i;
                            update=true;
                        }
                    }
                }
            }
            if(dis[t]==inf)
                return ans;
            int d=1;
    //		for(int v=t; v!=s; v=prevv[v])
    //		{
    //			d=min(d, e[prevv[v]][preve[v]].w);
    //		}
            ans+=d*dis[t];
            for(int v=t; v!=s; v=prevv[v])
            {
                edge &G = e[prevv[v]][preve[v]];
                G.w-=d;
                e[v][G.rev].w+=d;
            }
        }
        return ans;
    }
    int main()
    {
        int w;
        while(scanf("%d%d", &m, &n)!=EOF)
        {
            int s=0, t=n*(m+1)+1; 
            for(int i=1; i<=t; i++)
                e[i].clear();
            for(int i=1; i<=n; i++)
                for(int j=1; j<=m; j++)
                {
                    scanf("%d", &w);
                    for(int k=1; k<=n; k++)
                        add(i, j*n+k, 1, w * k);
                }
            for(int i=1; i<=n; i++)
                add(s, i, 1, 0);
            for(int i=n+1; i<t; i++)
                add(i, t, 1, 0);
            printf("%.2lf
    ", 1.0*min_cost(s, t)/n);
        }
        return 0;
    } 
  • 相关阅读:
    tar压缩
    sh脚本的dos和unix
    hive常用函数
    hive的union问题
    hive行转多列LATERAL VIEW explode
    Iterator和Enumeration
    基础啊基础
    一道考题---当n=1,2,3...2015时,统计3n+n3能整除7的个数
    自然语言处理
    矩阵相乘
  • 原文地址:https://www.cnblogs.com/zyq1758043090/p/11852523.html
Copyright © 2011-2022 走看看