【二分图匹配入门专题1】poj3686 【km+思维建图】
Description
The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receives N orders for toys. The manager knows that every order will take different amount of hours in different workshops. More precisely, the i-th order will take Zij hours if the toys are making in the j-th workshop. Moreover, each order's work must be wholly completed in the same workshop. And a workshop can not switch to another order until it has finished the previous one. The switch does not cost any time.
The manager wants to minimize the average of the finishing time of the N orders. Can you help him?
Input
The first line of input is the number of test case. The first line of each test case contains two integers, N and M (1 ≤ N,M ≤ 50).
The next N lines each contain M integers, describing the matrix Zij (1 ≤ Zij ≤ 100,000) There is a blank line before each test case.
Output
For each test case output the answer on a single line. The result should be rounded to six decimal places.
Sample Input
3
3 4
100 100 100 1
99 99 99 1
98 98 98 1
3 4
1 100 100 100
99 1 99 99
98 98 1 98
3 4
1 100 100 100
1 99 99 99
98 1 98 98
Sample Output
2.000000 1.000000 1.333333
题意:n个订单和m个机器,输入n*m的矩阵,矩阵值为每个机器处理一笔订单所花时间,每个机器只能处理完一笔订单后才能处理下一笔订单,问,最小的平均花费时间为多少。
思路:每个机器最多可以处理n个订单,假设处理每个订单花费时间为a1,a2,a3..an
那么一个机器处理n个订单花费的时间为a1+(a1+a2)+(a1+a2+a3)...= a1*n+a2*(n-1)+...an
第i订单倒数第k个处理时,耗费时间为ai*k.
我们把j机器倒数处理i订单的情况分为k个点,那么对于每一个订单i,在每个机器j上所花费的时间就是map[i][1..m*n]=cost*k
建图比较难想到,自己也是看了别人的题解才知道
~~~~今天成功被这两道题的bug给恶心的没谁了,这道题自己在判断增广路的if语句后加了一个分号;找bug的时间基本可以和写这道题的时间相当(泪目~),上一道题自己
把double变量定义为int型,还疑惑为什么精度不够,哎哎哎,自己这个样子以后还怎么愉快的刷题啊~~~
#include<stdio.h>
#include<string.h>
#define N 55
#define INF 0x3f3f3f3f
int map[N][N*N],visx[N],visy[N*N];
int linker[N*N],lx[N],ly[N*N];
int cost;
int n,m,nx,ny,d;
int dfs(int x)
{
int y,tmp;
visx[x] = 1;
for(y = 1; y <= ny; y ++)
{
if(!visy[y])
{
tmp = lx[x] + ly[y] - map[x][y];
if(!tmp)
{
visy[y] = 1;
if(linker[y]==-1||dfs(linker[y]))
{
linker[y] = x;
return 1;
}
}
else if(d > tmp)
d = tmp;
}
}
return 0;
}
int KM()
{
int sum,x,i,j;
memset(linker,-1,sizeof(linker));
memset(ly,0,sizeof(ly));
for(i = 1; i <= nx; i ++)
for(j = 1,lx[i]=-INF; j <= ny; j ++)
if(lx[i] < map[i][j])
{
lx[i] = map[i][j];
}
for(x= 1; x <= nx ; x ++)
{
while(1)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
d = INF;
if(dfs(x))//;就是这个bug!!!!
break;
for(i = 1; i <= nx; i ++)
if(visx[i])
lx[i] -= d;
for(i = 1; i <= ny; i ++)
if(visy[i])
ly[i] += d;
}
}
sum = 0;
for(i = 1; i <= ny; i ++)
if(linker[i]!=-1)
sum += map[linker[i]][i];
return -sum;
}
int main()
{
int t,sum;
double ans;
scanf("%d",&t);
while(t -- )
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i ++)
{
sum = 0;
for(int j = 1; j <= m;j ++)
{
scanf("%d",&cost);
for(int k = 1; k <= n; k ++)
map[i][++sum] = - k*cost;
}
}
nx = n;
ny = n*m;
ans = KM()*1.0/n;
printf("%.6lf\n",ans);
}
return 0;
}