P2053 [SCOI2007]修车

思路

很妙的网络流题目
最开始我简单的想直接把n个车的点和m个人员的点直接用cap=t(i,j)的边连起来,显然是假的,因为没有考虑到车主等待的时间长度
然后考虑分析将\(w_1,w_2,\dots,w_k\)个车主对总时间的贡献,总的等待时间是\(\sum_{i=1}^kw_i\times (k-i+1)\)让一个人在第i个位置修车时对总时间的贡献是\((n-i+1)\times w_i\)
所以搞出n*m代表第m个维修人员在n的时候维修一辆车的贡献,然后连边就行了

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int MAXN = 10000;
const int INF = 0x3f3f3f3f;
struct Edge{
    int u,v,cap,cost,flow;
};
vector<Edge> edges;
vector<int> G[MAXN];
int d[MAXN],a[MAXN],p[MAXN],vis[MAXN],s,t,n,m;
void addedge(int u,int v,int cap,int cost){
    edges.push_back((Edge){u,v,cap,cost,0});
    edges.push_back((Edge){v,u,0,-cost,0});
    int cnt=edges.size();
    G[u].push_back(cnt-2);
    G[v].push_back(cnt-1);
}
queue<int> q;
bool SPFA(int &flow,int &cost){
    memset(d,0x3f,sizeof(d));
    memset(p,0,sizeof(p));
    vis[s]=true;
    a[s]=INF;
    d[s]=0;
    vis[s]=true;
    q.push(s);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=false;
        for(int i=0;i<G[x].size();i++){
            Edge &e = edges[G[x][i]];
            if(e.cap>e.flow&&d[x]+e.cost<d[e.v]){
                d[e.v]=d[x]+e.cost;
                a[e.v]=min(a[x],e.cap-e.flow);
                p[e.v]=G[x][i];
                if(!vis[e.v]){
                    vis[e.v]=true;
                    q.push(e.v);
                }
            }
        }
    }
    if(d[t]==INF)
        return false;
    flow+=a[t];
    cost+=d[t]*a[t];
    for(int i=t;i!=s;i=edges[p[i]].u){
        edges[p[i]].flow+=a[t];
        edges[p[i]^1].flow-=a[t];
    }
    return true;
}
void MCMF(int &flow,int &cost){
   flow=0,cost=0;
   while(SPFA(flow,cost));
}
int main(){
    scanf("%d %d",&m,&n);
    s=MAXN-2;
    t=MAXN-3;
    for(int i=1;i<=n;i++)
        addedge(s,i,1,0);
    for(int i=1;i<=m;i++)
       for(int j=1;j<=n;j++)
            addedge(n+i+(j-1)*m,t,1,0);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            int t;
            scanf("%d",&t);
            for(int k=1;k<=n;k++)
                addedge(i,n+j+(k-1)*m,INF,k*t);
        }
    int cost=0,flow=0;
    MCMF(flow,cost);
    printf("%.2lf\n",1.0*cost/n);
    return 0;
}

原文地址:https://www.cnblogs.com/dreagonm/p/10485238.html

时间: 2024-10-09 07:02:23

P2053 [SCOI2007]修车的相关文章

[bzoj1070] [洛谷P2053] [SCOI2007] 修车

Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同 的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最 小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人 员维修第i辆车需要用的时间T. Output 最小平均等待时间,答案精确到小数点

P2053 [SCOI2007]修车 费用流

https://www.luogu.org/problemnew/show/P2053 题意 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. 思路 左边放n个点,表示n辆车.右边放m * n个点,表示m个工人,拆除n个点表示不同阶段.即如果第i辆车连上了第m个工人的第k个阶段

洛谷 P2053 [SCOI2007]修车

题目描述 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. 输入输出格式 输入格式: 第一行有两个数M,N,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T. 输出格式: 最小平均等待时间,答案精确到小数点后2位

P2053 [SCOI2007]修车 最小费用最大流

题目描述 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. 输入输出格式 输入格式: 第一行有两个数M,N,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T. 输出格式: 最小平均等待时间,答案精确到小数点后2位

luogu P2053 [SCOI2007]修车 |费用流

题目描述 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. 输入格式 第一行有两个数M,N,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T. 输出格式 最小平均等待时间,答案精确到小数点后2位. #includ

[SCOI2007]修车

1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 6007  Solved: 2559 [Submit][Status][Discuss] Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同 的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最 小. 说明:顾客的等待时间是指从他把车送至维修中心

BZOJ 1070: [SCOI2007]修车(最小费用最大流)

建图很神奇..建完图其实就是裸的费用流了.. -------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<queue> #define rep(i,n) for(int i

bzoj 1070: [SCOI2007]修车 -- 费用流

1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 128 MB Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m个整数.第

[bzoj1070][SCOI2007]修车_费用流

修车 bzoj-1070 SCOI-2007 题目大意:有m个人要修n台车,每个工人修不同的车的时间不同,问将所有的车都修完,最少需要花费的时间. 注释:$2\le m\le 9$,$1\le n \le 60$ 想法:想起了那句话...(如果题面复杂,dp状态不可描述,一看数据范围发现才几百,那八成是网络流了),一般这句话都是对的,除了那次在CF上遇到的爆搜.. ... 关于这道题,网上有题解在边上做技巧(完全没明白这样的意义),我的做法时拆点.将每个点拆成n个,然后在这些被拆的点与车之间连边