UVa10746 Crime Wave - The Sequel

        题意: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;
}


你可能感兴趣的:(图论,uva,最小费用最大流)