[BZOJ 1070] [SCOI2007] 修车

1070: [SCOI2007]修车

Time Limit: 1 Sec
Memory Limit: 162 MB

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)

【题解】

设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 }
View Code

 

posted @ 2015-07-11 19:21  TonyFang  阅读(215)  评论(0编辑  收藏  举报