这是一道网络流的题。
巨大的坑点→→这个输入第一行顺序是m,n。太坑了,WA了多次。
tyvj一定说我WA,下了数据明明对的,,,一脸懵逼。
贡献一下数据
输入
5 12
42 54 53 58 31
17 86 59 15 84
48 25 5 53 39
44 5 87 62 76
53 97 9 19 10
27 16 10 68 92
99 93 15 57 84
22 84 62 100 35
67 45 14 28 72
5 1 47 49 4
91 32 27 10 40
100 23 28 15 65输出
19.08
讲讲怎么做:这是一道网络流最小费用流。拆点是关键,首先取源点S想所有车连边,流量1费用0,然后将所有修车的m个人拆为n个点,即为他修倒数第几辆车,将车i与人j的k点连边,那么这条的费用就是k*a[i][j]
,流量为1,最后将所有人拆成的点与汇点T连边,跑最小费用最大流即可。
代码~~~:
/**************************************************************
Problem: 1070
User: fantasticwtl
Language: C++
Result: Accepted
Time:1296 ms
Memory:42484 kb
****************************************************************/
#include <cstdio>
#include <memory.h>//这个头文件类似cstring...
using namespace std;
int ans,n,m,w[2005][2005],d[500001],q[500001],pr[500001],a[2005][2005],qcn,cn;
bool ff[500005],f[2005][2005];
bool spfa ()
{
memset(ff,0,sizeof(ff));memset(pr,0,sizeof(pr));memset(d,120,sizeof(d));
ff[1]=1;q[1]=1;int h=0,t=1;d[1]=0;
while(h<t){
h++;
for(int i=2;i<=cn;i++)
if(f[q[h]][i]&&d[i]>d[q[h]]+w[q[h]][i]){
d[i]=d[q[h]]+w[q[h]][i];
pr[i]=q[h];
if(!ff[i])q[++t]=i,ff[i]=1;
}
ff[q[h]]=0;
}
if(d[cn]>1000000000)return 0;
ans+=d[cn];
return 1;
}
int main ()
{
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)scanf("%d",&a[i][j]);//读入部分
cn=1;
for(int i=1;i<=n;i++){
f[1][++cn]=1;
}
qcn=cn;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++){
cn++;
for(int k=2;k<=n+1;k++){
f[k][cn]=1;f[cn][qcn+m*n+1]=1;
w[k][cn]=j*a[k-1][i];
w[cn][k]=-w[k][cn];
}
}//建图部分
cn++;
while(spfa ()){//最小费用最大流
int k=cn;
while(k!=1)f[pr[k]][k]-=1,f[k][pr[k]]+=1,k=pr[k];
}
double ss=1.0*ans/n;//求平均等待时间
printf("%.2lf\n",ss);
}