BZOJ 1070 修车(最小费用流)

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1070

 同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同
的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最
小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。

  第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人
员维修第i辆车需要用的时间T。

 

思路:对每个顾客都建一个点,每个维修人员拆成n个点,代表是他修的第几辆车,这样子,由顾客连向维修人员的有向边,费用就是 等他的人数乘以他修车的时间。求费用流即可

 

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 int ans;
 7 int go[200005],tot,S,T,first[200005],next[200005],flow[200005];
 8 int cost[200005],c[200005],edge[200005],from[200005],a[500][500];
 9 int nodes,b[500][500],n,m,op[200005],dis[200005],vis[200005];
10 int read(){
11     int t=0,f=1;char ch=getchar();
12     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
13     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
14     return t*f;
15 }
16 void insert(int x,int y,int z,int l){
17     tot++;
18     go[tot]=y;
19     next[tot]=first[x];
20     first[x]=tot;
21     flow[tot]=z;
22     cost[tot]=l;
23 }
24 void add(int x,int y,int z,int l){
25     insert(x,y,z,l);op[tot]=tot+1;
26     insert(y,x,0,-l);op[tot]=tot-1;
27 }
28 bool spfa(){
29     for (int i=0;i<=T;i++) dis[i]=0x3f3f3f3f,vis[i]=0;
30     dis[S]=0;
31     int h=1,t=1;
32     c[1]=S;
33     while (h<=t){
34         int now=c[h++];
35         for (int i=first[now];i;i=next[i]){
36             int pur=go[i];
37             if (flow[i]&&dis[pur]>dis[now]+cost[i]){
38                 dis[pur]=dis[now]+cost[i];
39                 from[pur]=now;
40                 edge[pur]=i;
41                 if (vis[pur]) continue;
42                 vis[pur]=1;
43                 c[++t]=pur;
44             }
45         }
46         vis[now]=0;
47     }
48     return dis[T]!=0x3f3f3f3f;
49 }
50 void updata(){
51     int mn=0x7fffffff;
52     for (int i=T;i!=S;i=from[i]){
53         mn=std::min(mn,flow[edge[i]]);
54     }
55     for (int i=T;i!=S;i=from[i]){
56         flow[edge[i]]-=mn;
57         flow[op[edge[i]]]+=mn;
58         ans+=mn*cost[edge[i]];
59     }
60 }
61 int main(){
62     m=read();n=read();
63     for (int i=1;i<=n;i++){
64         for (int j=1;j<=m;j++){
65             a[i][j]=read();
66         }
67     }
68     S=0,T=n*m+n+1;
69     for (int i=1;i<=n;i++)
70      add(S,i,1,0);
71     nodes=n;
72     for (int i=1;i<=m;i++)
73       for (int k=1;k<=n;k++)
74        b[i][k]=++nodes,add(nodes,T,1,0);
75     for (int i=1;i<=n;i++)
76      for (int j=1;j<=m;j++)
77       for (int k=1;k<=n;k++)
78        add(i,b[j][k],1,k*a[i][j]);
79     while (spfa()) updata();
80     double Ans=(double)ans/n;
81     printf("%.2f\n",Ans);    
82 }

 

posted @ 2016-06-12 11:52  GFY  阅读(297)  评论(0编辑  收藏  举报