//坑爹的地方在于精度问题 //输出时要给结果加一个偏移量,否则,如 0.015 这样的数,会被输出成 0.01 是前人跟俺们的话! #include <iostream> #include <cstdio> #include <queue> #include <memory.h> using namespace std; const int MAX=25*2; const int INF=1<<30; bool inq[MAX]; int n,m,S,T; int cap[MAX][MAX],pa[MAX],flow[MAX][MAX]; double cost[MAX][MAX],d[MAX]; queue<int> q; double minCostMaxFlow(){ int u,v,a; double total=0.0; /*for(int i=0;i<=m;i++) for(int j=1;j<=n;j++) flow[i][m+j]=INF;*/ memset(flow,0,sizeof(flow)); while(1){ memset(inq,0,sizeof(inq)); //memset(pa,-1,sizeof(pa)); for(int i=0;i<=m+n+1;i++) d[i]=INF; d[S]=0.0; inq[S]=1; q.push(S); while(!q.empty()){ u=q.front(); q.pop(); inq[u]=0; for(v=0;v<=m+n+1;v++){ if(cap[u][v]>flow[u][v]&&d[v]>d[u]+cost[u][v]){ d[v]=d[u]+cost[u][v]; pa[v]=u; if(!inq[v]){ inq[v]=1; q.push(v); } } } } if(d[T]==INF) break; a=(int)INF; for(u=T;u!=S;u=pa[u]) if(a>cap[pa[u]][u]-flow[pa[u]][u]) a=cap[pa[u]][u]-flow[pa[u]][u]; for(u=T;u!=S;u=pa[u]){ flow[pa[u]][u]+=a; flow[u][pa[u]]-=a; } total+=d[T]*a; } return total; } int main() { freopen("i.txt","r",stdin); double t; S=0; while(cin>>n>>m){ if(!n&&!m) break; T=m+n+1; memset(cost,0,sizeof(cost)); /*for(int i=1;i<=m;i++){ for(int j=m+1;j<=m+n;j++){ cost[i][j]=INF; } }*/ memset(cap,0,sizeof(cap)); //connect the S vertex to each police for(int i=1;i<=m;i++){ //cost[0][i]=0.0; //cost[0][i]=0.0; cap[0][i]=1; } for(int i=m+1;i<=m+n;i++){ //cost[0][i]=0.0; //cost[i][T]=0.0; cap[i][T]=1; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>cost[j][m+i]; cost[m+i][j]=-cost[j][m+i];//important 表示沿着(u,v)方向增广时减小费用cost[u][v] //cout<<cost[j][m+i]<<" "; cap[j][m+i]=1; } //cout<<endl; } t=minCostMaxFlow(); printf("%.2lf/n",(t+1E-6)/n); t=0.0151; printf("%.2lf/n",t); } return 0; }