[luogu]P2053 [SCOI2007]修车
Posted onglublog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu]P2053 [SCOI2007]修车相关的知识,希望对你有一定的参考价值。
原题链接:P2053 [SCOI2007]修车
题意
有$n$辆车要修,有$m$个修理工,第$j$修理工修第$i$辆车有一个时间$r_{j,i}$。
求顾客最少的平均等待时间。
分析
由于$n$是给定的,所以最小的平均等待时间就是要求最小的总时间。
我们考虑怎么让总时间最短。
很容易发现第$i$辆车放在第$j$名修理工修,在$i$后面$j$还有还有$k$辆车要修时,$i$对总时间的贡献为$r_{j,i}*(n-p+1)$。
然后就可以用费用流解决这个问题。
我们可以把每个修理工拆成$n$个修理工,第$p$个修理工代表后面还有$n-p$辆车要修。
左边$n$个点表示车,右边$m*n$个点表示修理工,(以下所有边的容量均为1),源点向车连0边,车向修理工连$r_{j,i}*(n-p+1)$边,修理工向汇点连0边,跑最小费用最大流即可。
代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=107,M=17; 4 const int Ma=1000009; 5 int read(){ 6 char c;int num,f=1; 7 while(c=getchar(),!isdigit(c))if(c==‘-‘)f=-1;num=c-‘0‘; 8 while(c=getchar(), isdigit(c))num=num*10+c-‘0‘; 9 return f*num; 10 } 11 queue <int> q; 12 int n,m,maxflow,ans,r[M][N],dis[Ma],vis[Ma],pre[Ma],flow[Ma]; 13 int head[Ma],nxt[Ma],ver[Ma],cost[Ma],edge[Ma],tot=1,s,t; 14 void add(int u,int v,int w,int f){ 15 ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;edge[tot]=w;cost[tot]=f; 16 } 17 bool spfa(){ 18 while(q.size())q.pop(); 19 memset(dis,0x3f,sizeof(dis));dis[s]=0; 20 memset(vis,0 ,sizeof(vis));vis[s]=1; 21 q.push(s);flow[s]=0x3f3f3f3f; 22 while(q.size()){ 23 int x=q.front(); 24 vis[x]=0;q.pop(); 25 for(int i=head[x];i;i=nxt[i])if(edge[i]){ 26 int y=ver[i]; 27 if(dis[y]>dis[x]+cost[i]){ 28 dis[y]=dis[x]+cost[i]; 29 pre[y]=i; 30 flow[y]=min(flow[x],edge[i]); 31 if(!vis[y]){ 32 q.push(y); 33 vis[y]=1; 34 } 35 } 36 } 37 } 38 return dis[t]!=0x3f3f3f3f; 39 } 40 void update(){ 41 int x=t; 42 while(x!=s){ 43 int i=pre[x]; 44 edge[i]-=flow[t]; 45 edge[i^1]+=flow[t]; 46 x=ver[i^1]; 47 } 48 maxflow+=flow[t]; 49 ans+=dis[t]*flow[t]; 50 } 51 int main() 52 { 53 m=read();n=read(); 54 s=0;t=(m+1)*n+1; 55 for(int i=1;i<=n;i++) 56 for(int j=1;j<=m;j++) 57 r[j][i]=read(); 58 for(int i=1;i<=n;i++){ 59 add(s,i,1,0); 60 add(i,s,0,0); 61 } 62 for(int j=1;j<=m;j++){ 63 for(int p=1;p<=n;p++){ 64 for(int i=1;i<=n;i++){ 65 add(i,j*n+p,1,r[j][i]*(n-p+1)); 66 add(j*n+p,i,0,-r[j][i]*(n-p+1)); 67 } 68 add(j*n+p,t,1,0); 69 add(t,j*n+p,0,0); 70 } 71 } 72 while(spfa())update(); 73 printf("%.2f ",1.0*ans/n); 74 return 0; 75 } 76 77
以上是关于[luogu]P2053 [SCOI2007]修车的主要内容,如果未能解决你的问题,请参考以下文章