[SCOI2007]修车
https://www.luogu.org/problem/show?pid=2053
题目描述
同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。
说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
输入输出格式
输入格式:
第一行有两个数M,N,表示技术人员数与顾客数。
接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
输出格式:
最小平均等待时间,答案精确到小数点后2位。
输入输出样例
输入样例#1:
2 2 3 2 1 4
输出样例#1:
1.50
说明
(2<=M<=9,1<=N<=60), (1<=T<=1000)
#include<cstring> #include<cstdio> #include<queue> using namespace std; int m,n,src,decc,ans; int tim[10][61],dis[11*61],pre[11*61]; bool vis[11*61]; int front[11*61],to[36000*2],nxt[36000*2],tot=1,cap[36000*2],val[36000*2],from[36000*2]; void add(int u,int v,int w,int cost) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w; val[tot]=cost; from[tot]=u; to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=0; val[tot]=-cost; from[tot]=v; } bool spfa() { queue<int>q; memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis)); vis[0]=true; dis[0]=0; q.push(0); int now; while(!q.empty()) { now=q.front(); q.pop(); vis[now]=false; for(int i=front[now];i;i=nxt[i]) if(dis[to[i]]>dis[now]+val[i] && cap[i]>0) { dis[to[i]]=dis[now]+val[i]; pre[to[i]]=i; if(!vis[to[i]]) { q.push(to[i]); vis[to[i]]=true; } } } return dis[decc]<1e9; } void mcmf() { int i; for(i=pre[decc];from[i];i=pre[from[i]]) { ans+=val[i]; cap[i]--; cap[i^1]++; } cap[i]--; cap[i^1]++; } int main() { scanf("%d%d",&m,&n); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&tim[j][i]); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) add(j,(i-1)*n+k+n,1,k*tim[i][j]); decc=n*m+n+1; for(int i=n+1;i<decc;i++) add(i,decc,1,0); for(int i=1;i<=n;i++) add(src,i,1,0); while(spfa()) mcmf(); printf("%.2lf",ans*1.0/n); }