链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1070
同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同
的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最
小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人
员维修第i辆车需要用的时间T。
思路:对每个顾客都建一个点,每个维修人员拆成n个点,代表是他修的第几辆车,这样子,由顾客连向维修人员的有向边,费用就是 等他的人数乘以他修车的时间。求费用流即可
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
int ans;
int go[],tot,S,T,first[],next[],flow[];
int cost[],c[],edge[],from[],a[][];
int nodes,b[][],n,m,op[],dis[],vis[];
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y,int z,int l){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
flow[tot]=z;
cost[tot]=l;
}
void add(int x,int y,int z,int l){
insert(x,y,z,l);op[tot]=tot+;
insert(y,x,,-l);op[tot]=tot-;
}
bool spfa(){
for (int i=;i<=T;i++) dis[i]=0x3f3f3f3f,vis[i]=;
dis[S]=;
int h=,t=;
c[]=S;
while (h<=t){
int now=c[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (flow[i]&&dis[pur]>dis[now]+cost[i]){
dis[pur]=dis[now]+cost[i];
from[pur]=now;
edge[pur]=i;
if (vis[pur]) continue;
vis[pur]=;
c[++t]=pur;
}
}
vis[now]=;
}
return dis[T]!=0x3f3f3f3f;
}
void updata(){
int mn=0x7fffffff;
for (int i=T;i!=S;i=from[i]){
mn=std::min(mn,flow[edge[i]]);
}
for (int i=T;i!=S;i=from[i]){
flow[edge[i]]-=mn;
flow[op[edge[i]]]+=mn;
ans+=mn*cost[edge[i]];
}
}
int main(){
m=read();n=read();
for (int i=;i<=n;i++){
for (int j=;j<=m;j++){
a[i][j]=read();
}
}
S=,T=n*m+n+;
for (int i=;i<=n;i++)
add(S,i,,);
nodes=n;
for (int i=;i<=m;i++)
for (int k=;k<=n;k++)
b[i][k]=++nodes,add(nodes,T,,);
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
for (int k=;k<=n;k++)
add(i,b[j][k],,k*a[i][j]);
while (spfa()) updata();
double Ans=(double)ans/n;
printf("%.2f\n",Ans);
}