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. m (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 <=20. n 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; }