bzoj1070 修车 最小费用流

来源:互联网 发布:ebsco数据库免费入口 编辑:程序博客网 时间:2024/05/20 03:41

1070: [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 5655  Solved: 2383
[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个人分成m队,也就是每个修车师傅面前排一队人,其中这个队里的第k个人等待时间是k*这个人在该技术工人这里修车的时间T;

       那么,也就是说把这n个人分配到m个队中的某个位置上,每个人只分配一次,每个位置只有一个人。

       因此,可以用网络流来解决。图中共有1个源点,1个汇点,n个节点代表n个人(人节点 ),n*m个节点代表每个队列中的每个位置(位置节点)。从源点向每个人节点连一条容量为1,费用是0的边;从每个人节点向每个位置节点连一条边,容量为1,费用是这个人站在这个队列的这个位置时的花费;每个位置节点向汇点连一条容量是1,费用是0的边。跑一遍源点到汇点的最小费用最大流得到答案。

      看了一下status,速度差距明显,查了一下网上题解的做法,认为有必要学一下zkw费用流。

#pragma warning(disable:4786)#pragma comment(linker, "/STACK:102400000,102400000")#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>#include<queue>#include<map>#include<set>#include<vector>#include<cmath>#include<string>#include<sstream>#include<bitset>#define LL long long#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)#define mem(a,x) memset(a,x,sizeof(a))#define lson l,m,x<<1#define rson m+1,r,x<<1|1using namespace std;const int INF = 0x3f3f3f3f;const int mod = 1e9 + 7;const double PI = acos(-1.0);const double eps=1e-6;const int maxn = 700;int c[65][15];struct Edge{    int from , to , cap , flow , cost;};struct MCMF{    int n, m ,s , t;    vector<Edge>edges;    vector<int>G[maxn];    int d[maxn] , p[maxn] , a[maxn] , inq[maxn];    void init(int n){        this -> n = n;        for(int i = 0 ; i <= n ; i++)       G[i].clear();        edges.clear();    }    void AddEdge(int from , int to , int cap , int cost){        Edge e1 = {from , to , cap , 0 , cost};        Edge e2 = {to , from , 0 , 0  , -cost};        edges.push_back(e1);        edges.push_back(e2);        int m = edges.size();        G[from].push_back(m - 2);        G[to].push_back(m - 1);    }    bool BellmanFord(int s , int t , int & flow , LL & cost){        mem(d , INF);        d[s] = 0;   p[s] = 0;   a[s] = INF;        mem(inq , 0);   inq[s] = 1;        queue<int>Q;        Q.push(s);        while(!Q.empty()){            int x = Q.front();      Q.pop();            inq[x] = 0;            for(int i = 0 ; i < G[x].size() ; i++){                Edge & e = edges[G[x][i]];                if(e.cap > e.flow && d[e.to] > d[x] + e.cost){                    d[e.to] = d[x] + e.cost;                    p[e.to] = G[x][i];                    a[e.to] = min(a[x] , e.cap - e.flow);                    if(!inq[e.to]){                        Q.push(e.to);                        inq[e.to] = 1;                    }                }            }        }        if(d[t] == INF)     return false;        flow += a[t];        cost += (LL)a[t] * (LL)d[t];        int u = t;        while(u != s){            edges[p[u]].flow += a[t];            edges[p[u]^1].flow -= a[t];            u = edges[p[u]].from;        }        return true;    }    LL Mincost(int s , int t , int & flow){        flow = 0;        LL cost = 0;        while(BellmanFord(s , t , flow , cost))     ;        return cost;    }}g;int main(){    int n , m;    while(scanf("%d %d" , &m , &n) != EOF){        for(int i = 1 ; i <= n ; i++){            for(int j = 1 ; j <= m ; j++){                scanf("%d" , &c[i][j]);            }        }        g.init(2 + n * m + n);        int source = 1 , sink = 2 + n * m + n;        for(int i = 1 ; i <= n; i++){            g.AddEdge(source , 1 + i , 1 , 0);            for(int j = 1 ; j <= m ; j++){                for(int k = 1 ; k <= n; k++){                    g.AddEdge(i + 1 , 1 + n + n * (j - 1) + k , 1 , k * c[i][j]);                }            }        }        for(int j = 1 ; j <= m ; j++){            for(int k = 1 ; k <= n; k++){                g.AddEdge(1 + n + n * (j - 1) + k , sink , 1 , 0);            }        }        int flow ;        double ans = (double)g.Mincost(source , sink , flow);        ans = ans / n;        printf("%.2lf\n" , ans);    }    return 0;}


原创粉丝点击