题意:n个银行,m个警察(n<=m)。每个银行需要一个警察去守。给出所有警察到所有银行的花费,问怎么安排警察最省。
思路:最小费用最大流。建图:源点->银行->警察->汇点。注意反向边费用要赋上正向边的相反数,另外可能出现精度问题。这道题本来是简单题,但是我把return 0写成了return true,RE一万年找不出原因。。。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
#define INF 1000000000
using namespace std;
int n,m;
int map[50][50];
int f[50][50];
double cost[50][50];
int pre[50];
int main(){
while(cin>>n>>m){
if(n==0&&m==0)break;
memset(map,0,sizeof(map));
memset(f,0,sizeof(f));
for(int i=0;i<=n+m+1;i++)
for(int j=0;j<=n+m+1;j++)
cost[i][j]=0;
//for(int i=1;i<=n;i++)map[0][i]=1;
for(int i=1;i<=m;i++)map[n+i][n+m+1]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>cost[i][n+j];
cost[n+j][i]=-cost[i][n+j];
map[i][n+j]=1;
}
}
double cc[50];
bool vis[50];
double ans=0;
for(int k=1;k<=n;k++){
memset(vis,0,sizeof(vis));
for(int i=1;i<=m+n+1;i++)cc[i]=INF;
cc[k]=0;
queue<int> que;que.push(k);
while(!que.empty()){
int cur=que.front();que.pop();vis[cur]=false;
for(int i=1;i<=n+m+1;i++){
if( (cc[cur]+cost[cur][i])<cc[i]-0.0001 &&(map[cur][i]-f[cur][i])>0 ){
pre[i]=cur;
cc[i]=(cc[cur]+cost[cur][i]);
if(!vis[i]){
vis[i]=true;
que.push(i);
}
}
}
}
ans+=cc[n+m+1];
for(int i=n+m+1;i!=k;i=pre[i]){
f[pre[i]][i]++;
f[i][pre[i]]--;
}
}
printf("%.2lf\n",ans/n-0.00000001);
}
return 0;
}