[SCOI2007]修车

1070: [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 6007  Solved: 2559 [Submit][Status][Discuss]

Description

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

Input

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

Output

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

Sample Input

2 2
3 2
1 4

Sample Output

1.50

HINT

数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)

对于每个维修师傅拆成$n$个点,每个点在连边时费用对应乘上相应的倍数,因为如果一个维修师傅修多个车的话等待时间需要乘上一定倍数。然后跑最小费用最大流

#include <cstdio>
inline int readint(){
    int f = 1, n = 0;
    char ch = getchar();
    while(ch < ‘0‘ || ch > ‘9‘){
        if(ch == ‘-‘) f = -1;
        ch = getchar();
    }
    while(ch <= ‘9‘ && ch >= ‘0‘){
        n = (n << 1) + (n << 3) + ch - ‘0‘;
        ch = getchar();
    }
    return f * n;
}
const int maxn = 100, maxm = 15, INF = 0x3f3f3f3f;
struct Edge{
    int to, cap, cost, next;
    Edge(){}
    Edge(int _t, int _w, int _c, int _n): to(_t), cap(_w), cost(_c), next(_n){}
}e[maxn + maxn * maxn * maxm + maxn * maxm << 1];
int fir[maxn + maxn * maxm] = {0}, cnt = 1;
inline void ins(int u, int v, int w, int c){
    e[++cnt] = Edge(v, w, c, fir[u]); fir[u] = cnt;
    e[++cnt] = Edge(u, 0, -c, fir[v]); fir[v] = cnt;
}
int sour, sink;
bool inq[maxn + maxn * maxm] = {false};
int dis[maxn + maxn * maxm];
int q[maxn + maxn * maxm], head, tail;
int pre[maxn + maxn * maxm];
bool SPFA(){
    for(int i = sour; i <= sink; i++){
        dis[i] = INF;
        inq[i] = false;
        pre[i] = 0;
    }
    head = tail = 0;
    dis[sour] = 0;
    inq[sour] = true;
    q[tail++] = sour;
    int u, v;
    while(head != tail){
        u = q[head++];
        if(head == 1600) head = 0;
        inq[u] = false;
        for(int i = fir[u]; i; i = e[i].next){
            v = e[i].to;
            if(e[i].cap && dis[v] > dis[u] + e[i].cost){
                dis[v] = dis[u] + e[i].cost;
                pre[v] = i;
                if(!inq[v]){
                    inq[v] = true;
                    q[tail++] = v;
                    if(tail == 1600) tail = 0;
                }
            }
        }
    }
    return dis[sink] != INF;
}
int MCMF(){
    int flow, cost = 0;
    while(SPFA()){
        flow = INF;
        for(int i = pre[sink]; i; i = pre[e[i ^ 1].to])
            if(e[i].cap < flow) flow = e[i].cap;
        for(int i = pre[sink]; i; i = pre[e[i ^ 1].to]){
            e[i].cap -= flow;
            e[i ^ 1].cap += flow;
        }
        cost += flow * dis[sink];
    }
    return cost;
}
int main(){
    int m, n;
    m = readint();
    n = readint();
    sour = 0;
    sink = n + n * m + 1;
    for(int i = 1; i <= n; i++) ins(sour, i, 1, 0);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++){
            int t = readint();
            for(int k = 1; k <= n; k++)
                ins(i, j * n + k, 1, k * t);
        }
    for(int i = 1; i <= m; i++)
        for(int j = 1; j <= n; j++)
            ins(i * n + j, sink, 1, 0);
    printf("%.2lf\n", MCMF() * 1.0 / n);
    return 0;
}
时间: 2024-10-14 18:55:06

[SCOI2007]修车的相关文章

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个,然后在这些被拆的点与车之间连边

[BZOJ 1070][SCOI2007]修车(费用流)

Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Solution 非常经典的建图方式,将每一位技术人员拆成n个点分别他是表示倒数第几个修车的,倒数第k个修车的技术人员对所有在等待的人的贡献是tim[i][j]*k #include<iostream>

[BZOJ 1070] [SCOI2007] 修车 【费用流】

题目链接:BZOJ - 1070 题目分析 首先想到拆点,把每个技术人员拆成 n 个点,从某个技术人员拆出的第 i 个点,向某辆车连边,表示这是这个技术人员修的倒数第 i 辆车.那么这一次修车对整个答案的贡献就是,i * Time[j][k]. j 是车的编号,k 是技术人员编号.因为这辆车以及之后这个人要修的车的等待时间都增加了 Time[j][k], 所以包括这辆车在内一共有 i 辆车的等待时间加上了这次修车的时间.这样倒着考虑就可以用边的费用很简便的表示修车使所有人增加的时间了.从 S 到

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

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

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 <

Bzoj1070 [SCOI2007]修车

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

bzoj 1070: [SCOI2007]修车

1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define M 10000 5 #define inf 2139062143 6 using namespace std; 7 int cnt=1,n,m,T,d[M],q[2*M],f[M],head[M],next[10*M],u[10*M],v[10*M],w[10*M],fro[10*M],fr[M]; 8 int mp[100][10