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
3 2
1 4
Sample Output
1.50
HINT
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
将M个工作人员拆成N个点
拆后的M员工的第k个裂点连某辆车,表示该车是倒数第k个被修的车
因为是倒数第k,所以费用自然要加上后面排队的车的费用
算是一种逆向思维吧
MD n和m搞反了……找错找了半天qwq
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define MAXN (50000+10)
#define MAXM (5000000+10)
using namespace std;
queue<int>q;
bool visit[MAXN];
int pre[MAXN];
int n,m,k,s,e=4999,Ans,Fee;
int num_edge;
int head[MAXN];
int dis[MAXN];
bool used[MAXN];
int INF;
int t[1000][1000];
struct node
{
int to;
int next;
int Flow;//残留网络
int Cost;
} edge[MAXM*2];
void add(int u,int v,int l,int c)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
edge[num_edge].Flow=l;
edge[num_edge].Cost=c;
head[u]=num_edge;
}
bool Spfa(int s,int e)
{
memset(pre,-1,sizeof(pre));
memset(dis,0x7f,sizeof(dis));
q.push(s);
dis[s]=0;
used[s]=true;
while (!q.empty())
{
int x=q.front();
q.pop();
for (int i=head[x]; i!=0; i=edge[i].next)
if (dis[x]+edge[i].Cost<dis[edge[i].to] && edge[i].Flow>0)
{
dis[edge[i].to]=edge[i].Cost+dis[x];
pre[edge[i].to]=i;
if (!used[edge[i].to])
{
used[edge[i].to]=true;
q.push(edge[i].to);
}
}
used[x]=false;
}
return (dis[e]!=INF);
}
int MCMF(int s,int e)
{
Ans=0,Fee=0;
while (Spfa(s,e))
{
int d=INF;
for (int i=e; i!=s; i=edge[((pre[i]-1)^1)+1].to)
d=min(d,edge[pre[i]].Flow);
for (int i=e; i!=s; i=edge[((pre[i]-1)^1)+1].to)
{
edge[pre[i]].Flow-=d;
edge[((pre[i]-1)^1)+1].Flow+=d;
}
Ans+=d;
Fee+=d*dis[e];
}
return Fee;
}
int main()
{
memset(&INF,0x7f,sizeof(INF));
scanf("%d%d",&m,&n);
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
scanf("%d",&t[i][j]);
for (int i=1;i<=m*n;++i)
{
add(s,i,1,0);
add(i,s,0,0);
}
for (int i=1;i<=n;++i)
{
add(m*n+i,e,1,0);
add(e,m*n+i,0,0);
}
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
for (int k=1;k<=n;++k)
{
add((j-1)*n+i,m*n+k,1,i*t[k][j]);
add(m*n+k,(j-1)*n+i,0,-i*t[k][j]);
}
double ans=MCMF(s,e);
printf("%.2lf\n",ans/n);
}