[BZOJ 1070] [SCOI2007] 修车
1070: [SCOI2007]修车
Time Limit: 1 SecDescription
同一时刻有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)
【题解】
设time[i][j]表示第i部车被第j个修理人员修的时间.
把每个维修人员拆成n个点,表示是倒数第几个修的.再建n个点表示n部车.
那么如果第i部车,是在第j个维修人员那里作为倒数第z个修,那么就像i->(j,z)连一条费用(影响)是 time[i][j]*z (要加上自己的哦.),容量为1的边.
再向源点到n部车的点连一条容量为1费用为0的边,表示每部车只有一辆.
每个表示第j个维修人员,倒数第z个修的点(j,z)向汇点连一条容量为1费用为0的边,表示第j个维修人员,倒数第z个修的车,只能有一辆.
这构图真是机智。。。然而我太弱了只好多见识见识机智的构图模型咯
现在费用流写的有点熟了呢~
1 #include <stdio.h> 2 #include <queue> 3 #include <string.h> 4 using namespace std; 5 const int B=200100; 6 int head[B], timx[1010][1010], S, T, n, m, cnt=-1, next[B], to[B], w[B], flow[B], d[B], pre[B]; 7 bool vis[B]; 8 int oq[B]; 9 int ans; 10 double ans2; 11 queue<int> q; 12 13 inline void qclean() { 14 while(!q.empty()) q.pop(); 15 } 16 inline void addf(int u,int v,int _flow,int _w) { 17 ++cnt; 18 to[cnt]=v; 19 next[cnt]=head[u]; 20 head[u]=cnt; 21 flow[cnt]=_flow; 22 w[cnt]=_w; 23 } 24 inline void add(int u,int v,int _flow,int _w) { 25 addf(u,v,_flow,_w); 26 addf(v,u,0,-_w); 27 } 28 inline bool spfa() { 29 qclean(); 30 memset(d,0X7f,sizeof(d)); 31 memset(vis,0,sizeof(vis)); 32 memset(oq,0,sizeof(oq)); 33 memset(pre,-1,sizeof(pre)); 34 pre[S]=-1; d[S]=0; vis[S]=1; q.push(S); 35 while(!q.empty()) { 36 int top=q.front(); q.pop(); 37 vis[top]=0; 38 for (int i=head[top];i>=0;i=next[i]) { 39 if(d[top]+w[i]<d[to[i]]&&flow[i]) { 40 d[to[i]]=d[top]+w[i]; 41 pre[to[i]]=i; 42 if(!vis[to[i]]) { 43 vis[to[i]]=1; 44 q.push(to[i]); 45 } 46 } 47 } 48 } 49 return pre[T]!=-1; 50 } 51 inline void mcf() { 52 int xm=1e9; 53 for (int k=pre[T];k>=0;k=pre[to[k^1]]) 54 xm=min(xm,flow[k]); 55 for (int k=pre[T];k>=0;k=pre[to[k^1]]) { 56 flow[k]-=xm; 57 flow[k^1]+=xm; 58 ans+=xm*w[k]; 59 } 60 } 61 int main() { 62 scanf("%d%d",&m,&n); 63 S=0; T=n*m+n+1; 64 memset(head,-1,sizeof(head)); 65 for (int i=1;i<=n;++i) 66 for (int j=1;j<=m;++j) scanf("%d",&timx[i][j]); 67 for(int i=1;i<=n;i++) add(S,i,1,0); 68 for(int i=n+n*m;i>=n+1;i--) add(i,T,1,0); 69 for(int i=1;i<=n;i++) 70 for(int j=1;j<=m;j++) 71 for(int k=1;k<=n;k++) 72 add(i,j*n+k,1,(n-k+1)*timx[i][j]); 73 while(spfa()) mcf(); 74 printf("%.2lf\n",(double)ans/n); 75 return 0; 76 }
这篇文章由TonyFang发布。
所有解释权归TonyFang所有。
Mailto: tony-fang@map-le.net