bzoj1070

 

1070: [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 6295  Solved: 2679
[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)

  费用流。把车看作点,S向每辆车连容量1费用0的点。

  把每个工人拆成n个点,k点表示倒数第k个修这辆车。

  每个工人点向T连容量1费用0的边。

  每辆车向每个工人点连边,容量1,费用为k*cost,k即为这个工人倒数第k个修这辆车。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
#define N 105
using namespace std;
int n,m,tot,S,T,base,t[N][N],hd[N*N],vis[N*N],d[N*N],pre[N*N],a[N*N];
struct edge{int u,v,w,next,cap;}e[N*N*6];
bool spfa(int &flow,int &cost){
    queue<int>q;
    memset(pre,-1,sizeof(pre));
    memset(d,0x3f,sizeof(d));
    q.push(S);d[S]=0;a[S]=0x3f3f3f3f;
    while(!q.empty()){
        int u=q.front();q.pop();
        vis[u]=0;
        for(int i=hd[u];~i;i=e[i].next){
            int v=e[i].v;
            if(e[i].cap>0&&d[v]>d[u]+e[i].w){
                d[v]=d[u]+e[i].w;pre[v]=i;
                a[v]=min(a[u],e[i].cap);
                if(vis[v])continue;
                vis[v]=1;q.push(v);
            }
        }
    }
    if(d[T]==0x3f3f3f3f)return 0;
    flow+=a[T];cost+=a[T]*d[T];
    int u=T;
    while(u!=S){
        e[pre[u]].cap-=a[T];
        e[pre[u]^1].cap+=a[T];
        u=e[pre[u]].u;
    }
    return 1;
}
void adde(int u,int v,int w,int cap){
    e[tot].u=u;e[tot].next=hd[u];e[tot].v=v;
    e[tot].w=w;e[tot].cap=cap;hd[u]=tot++;
}
int get(int i,int j){return (j-1)*m+i;}
void build(int i,int j,int k){
    adde(i+base,get(j,k),k*t[j][i],1);
    adde(get(j,k),i+base,-k*t[j][i],0);
//    printf("%d %d %d\n",i+base,get(j,k),k*t[j][i]);
} 
int main(){
    scanf("%d%d",&m,&n);
    memset(hd,-1,sizeof(hd));
    base=n*m;S=0;T=base+n+1;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)scanf("%d",&t[j][i]);    
    for(int i=1;i<=n;i++)adde(S,i+base,0,1),adde(i+base,S,0,0)/*printf("%d %d 0\n",S,i+base)*/;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
    for(int k=1;k<=n;k++)build(i,j,k);
    for(int i=1;i<=base;i++)adde(i,T,0,1),adde(T,i,0,0)/*printf("%d %d 0\n",i,T)*/;
    int flow=0,cost=0;
    while(spfa(flow,cost));
    printf("%.2lf",(double)cost/n);
    return 0;
}

  

posted @ 2017-11-30 22:11  _wsy  阅读(208)  评论(0编辑  收藏  举报