BZOJ1070 [SCOI2007]修车
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
3 2
1 4
Sample Output
1.50
HINT
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
正解:网络流最小费用最大流
解题报告:建图有点神奇,对于每一个维修人员建n个点,表示这是他修的倒数第几辆,那么当前的车只会影响后面的车的等待时间,假如现在是倒数第j辆车,那么花费就是j*f【i】【k】,f【i】【k】表示第i个维修工人修序号为k的车的花费。然后n辆车连上n*m个点,容量为1,车再向源点点连容量为1的边,n*m个点向汇点连容量为1的边,跑spfa。
1 #include <iostream> 2 #include <iomanip> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <cmath> 6 #include <cstring> 7 #include <string> 8 #include <algorithm> 9 #define MIN(a,b) a<b?a:b 10 #define RG register 11 const int N = 5000; 12 const int M = 1000000; 13 const int inf = 2147483641; 14 15 using namespace std; 16 17 int gi(){ 18 char ch=getchar();int x=0; 19 while(ch<'0' || ch>'9') ch=getchar(); 20 while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); 21 return x; 22 } 23 24 int n,m,q,ans,cnt=1,S,T; 25 int fa[N],f[N][N],nxt[M],c[N][N],head[N],s[M],dis[M],vis[M]; 26 27 struct date{ 28 int from,to,val,s; 29 }nn[M]; 30 31 void link(int l,int r,int val,int s){ 32 nn[++cnt]=(date){l,r,val,s},nxt[cnt]=head[l],head[l]=cnt; 33 nn[++cnt]=(date){r,l,0,-s},nxt[cnt]=head[r],head[r]=cnt; 34 return; 35 } 36 37 int spfa(){ 38 int l=0,r=1; 39 for (RG int i=S; i<=T; ++i) dis[i]=inf; 40 s[1]=0,dis[0]=0,vis[0]=1; 41 while(l<r){ 42 ++l; 43 for (RG int i=head[s[l]]; i; i=nxt[i]) 44 if (nn[i].val && dis[nn[i].to]>dis[s[l]]+nn[i].s){ 45 fa[nn[i].to]=i; 46 dis[nn[i].to]=dis[s[l]]+nn[i].s; 47 if (!vis[nn[i].to]){ 48 vis[nn[i].to]=1;s[++r]=nn[i].to; 49 } 50 } 51 vis[s[l]]=0; 52 } 53 if (dis[T]==inf) return 0; 54 int tmp=inf; 55 for (RG int i=fa[T]; i; i=fa[nn[i].from]) tmp=MIN(tmp,nn[i].val); 56 for (RG int i=fa[T]; i; i=fa[nn[i].from]) nn[i].val-=tmp,nn[i^1].val+=tmp; 57 ans+=tmp*dis[T]; 58 return 1; 59 } 60 61 int main(){ 62 m=gi(),n=gi(); 63 for (RG int i=1; i<=n; ++i) link(S,i,1,0); 64 for (RG int i=1; i<=n; ++i) 65 for (RG int j=1; j<=m; ++j) 66 f[j][i]=gi(); 67 ans=n,q=n; 68 for (RG int i=1; i<=m; ++i) 69 for (RG int j=1; j<=q; ++j) 70 c[i][j]=++ans; 71 T=ans+1; 72 ans=0; 73 for (RG int i=1; i<=n; ++i) 74 for (RG int j=1; j<=m; ++j) 75 for (RG int k=1; k<=q; ++k) 76 link(i,c[j][k],1,f[j][i]*k); 77 for (RG int j=1; j<=m; ++j) 78 for (RG int k=1; k<=q; ++k) 79 link(c[j][k],T,1,0); 80 ans=0; 81 while(spfa()); 82 printf("%.2lf",(ans*1.0)/n); 83 return 0; 84 }