首页 > 代码库 > UVA 10746 Crime Wave – The Sequel(费用流)

UVA 10746 Crime Wave – The Sequel(费用流)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1687

ProblemG

CrimeWave – The Sequel

Input: StandardInput

Output: StandardOutput

TimeLimit: 2 Seconds

 

n bankshave been robbed this fine day. (greater than orequal to n) police cruisers are on duty at variouslocations in the city. n of the cruisers should bedispatched, one to each of the banks, so as to minimize the averagetime of arrival at the n banks.

 

Input

Theinput file contains several sets of inputs. The description of eachset is given below:

Thefirst line of input contains 0 < n <= m <=20n lines follow, each containing m positivereal numbers: the travel time for cruiser m to reachbank n.

Inputis terminated by a case where m=n=0. This case should notbe processed.  

Output

Foreach set of input output a single number: the minimum average traveltime, accurate to 2 fractional digits.

 

SampleInput                             Outputfor Sample Input

3 4
10.0 23.0 30.0 40.0
5.0 20.0 10.0 60.0
18.0 20.0 20.0 30.0

00

13.33


Problemsetter: GordonCormack, EPS


题意:

有m个警察,派n个警察到n个银行,给出每个警察到各银行的时间,求最小的平均时间。

分析:

平均乘上n就是总时间,也就是要最小化总时间,那么用费用流就可以解决问题。各银行向每个警察连边,容量1,费用为时间;增加源点,源点向各银行连边,容量1,费用0;增加汇点,警察向汇点连边,容量1,费用0。在图中跑费用流就行。

这题最恶心的地方在于保留小数,结果加上eps再输出。这里涉及到保留小数方法,是用传统的四舍五入还是用银行家舍入?都不知道以后涉及到小数的输出要怎么搞了,这种东西就该spj啊。


/*
 *
 *	Author	:	fcbruce
 *
 *	Date	:	2014-09-05 20:37:26 
 *
 */
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10

#ifdef _WIN32
	#define lld "%I64d"
#else
	#define lld "%lld"
#endif

#define maxm 2333
#define maxn 64

using namespace std;

int fir[maxn];
int u[maxm],v[maxm],cap[maxm],flow[maxm],nex[maxm];
double cost[maxm];
int e_max;
double d[maxn];
int p[maxn];
bool inq[maxn];
int q[maxm<<3];

inline void add_edge(int _u,int _v,int _cap,double _cost)
{
	int e;
	e=e_max++;
	u[e]=_u;v[e]=_v;cap[e]=_cap;cost[e]=_cost;
	nex[e]=fir[u[e]];fir[u[e]]=e;
	e=e_max++;
	u[e]=_v;v[e]=_u;cap[e]=0;cost[e]=-_cost;
	nex[e]=fir[u[e]];fir[u[e]]=e;
}

void SPFA(int s)
{
	memset(inq,0,sizeof inq);
	memset(d,0x7f,sizeof d);
	int f,r;
	d[s]=0;
	q[f=r=0]=s;
	while (f<=r)
	{
		int x=q[f++];
		inq[x]=false;
		for (int e=fir[x];~e;e=nex[e])
		{
			if (cap[e]>flow[e] && d[v[e]]>d[u[e]]+cost[e]+eps)
			{
				d[v[e]]=d[u[e]]+cost[e];
				p[v[e]]=e;
				if (!inq[v[e]])
				{
					inq[v[e]]=true;
					q[++r]=v[e];
				}
			}
		}
	}
}

pair<double,int> min_cost_flow(int s,int t)
{
	memset(flow,0,sizeof flow);
	double total_cost=0;
	int total_flow=0;
	
	for (;;)
	{
		SPFA(s);
		
		if (d[t]>INF)	break;
		
		int _f=INF;
		for (int e=p[t];;e=p[u[e]])
		{
			_f=min(_f,cap[e]-flow[e]);
			if (u[e]==s)	break;
		}
		
		for (int e=p[t];;e=p[u[e]])
		{
			flow[e]+=_f;
			flow[e^1]-=_f;
			if (u[e]==s)	break;
		}
		
		total_cost+=d[t]*_f;
		total_flow+=_f;
	}
	
	return make_pair(total_cost,total_flow);
}

int main()
{
#ifdef FCBRUCE
	freopen("/home/fcbruce/code/t","r",stdin);
#endif // FCBRUCE
	
	int n,m;
	
	while (scanf( "%d%d",&n,&m),n||m)
	{
		int s=0,t=n+m+1;
		
		e_max=0;
		memset(fir,-1,sizeof fir);
		
		double w;
		for (int i=1;i<=n;i++)
		{
			for (int j=1;j<=m;j++)
			{
				scanf( "%lf",&w);
				add_edge(i,n+j,1,w);
			}
		}
		
		for (int i=1;i<=n;i++)
			add_edge(s,i,1,0);
		
		for (int j=1;j<=m;j++)
			add_edge(j+n,t,1,0);
		
		auto res=min_cost_flow(s,t);
		
		printf( "%.2f\n",res.first/res.second+eps);
	}
	
	return 0;
}



UVA 10746 Crime Wave – The Sequel(费用流)