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

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 }

 

posted @ 2017-02-25 15:54  Cjk_2001  阅读(145)  评论(0编辑  收藏  举报