「BZOJ1070」[SCOI2007]修车

求平均时间最小就是求总时间最小

假设每个顾客对应的技术人员已经分配好了

那么技术人员在修某一辆车时对答案的贡献就是 time × 在排队的人数

所以可以想到把技术人员拆成n个点{mi1,mi2 ,……,min }

对于每个顾客,向mij连一条容量为1,花费为 time*j 的边

求这个二分图的最大权匹配

可以用KM算法或费用流

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1000,oo=1e9;
 4 int n,m,ss,tt;
 5 struct Edge{
 6     int from,to,flow,cap,cost;
 7     Edge(int _from=0,int _to=0,int _flow=0,int _cap=0,int _cost=0):from(_from),to(_to),flow(_flow),cap(_cap),cost(_cost){}
 8 };
 9 vector<Edge>edge;
10 int edge_tot;
11 vector<int>point[N];
12 void add_edge(int f,int t,int c,int cc){
13     edge.push_back(Edge(f,t,0,c,cc));
14     point[f].push_back(edge_tot++);
15     edge.push_back(Edge(t,f,0,0,-cc));
16     point[t].push_back(edge_tot++);
17     return;
18 }
19 int dis[N],pre[N];
20 bool spfa(){
21     memset(dis,127/2,sizeof(dis));
22     queue<int>q;
23     q.push(ss);
24     dis[ss]=0;
25     int x;
26     while(!q.empty()){
27         x=q.front();q.pop();
28         for(int i=0;i<point[x].size();i++){
29             Edge& e=edge[point[x][i]];
30             if(e.cap>e.flow&&dis[e.to]>dis[x]+e.cost){
31                 dis[e.to]=dis[x]+e.cost,pre[e.to]=point[x][i];
32                 q.push(e.to);
33             }
34         }
35     }
36     return dis[tt]<oo;
37 }
38 int mincostmaxflow(){
39     int now,minf,ans=0;
40     while(spfa()){
41         minf=oo,now=tt;
42         while(now!=ss){
43             minf=min(minf,edge[pre[now]].cap-edge[pre[now]].flow);
44             now=edge[pre[now]].from;
45         }
46         now=tt,ans+=minf*dis[tt];
47         while(now!=ss){
48             edge[pre[now]].flow+=minf,edge[pre[now]^1].flow-=minf;
49             now=edge[pre[now]].from;
50         }
51     }
52     return ans;
53 }
54 int main(){
55     int t1;
56     scanf("%d%d",&m,&n);
57     ss=n*m+n+1,tt=ss+1;
58     for(int i=1;i<=n;i++)
59         for(int j=1;j<=m;j++){
60             scanf("%d",&t1);
61             for(int k=0;k<n;k++) add_edge(m*n+i,k*m+j,1,t1*(k+1));
62         }
63     for(int i=1;i<=n;i++) add_edge(ss,i+m*n,1,0);
64     for(int i=1;i<=m*n;i++) add_edge(i,tt,1,0);
65     printf("%.2lf",1.0*mincostmaxflow()/n);
66     return 0;
67 }

 

posted @ 2018-03-08 13:20  Cupcake  阅读(115)  评论(0编辑  收藏  举报