poj3686The Windy's (KM)

时间:2024-01-20 21:20:21

http://poj.org/problem?id=3686

拆点很巧妙 将每个M个点拆成m*n个点 分别表示第i个玩具在第j个机器上倒数第K个处理

假设这k个玩具真正用在加工的时间分为a1,a2,a3...ak, 那么每个玩具实际的时间是加工的时间+等待时间,分别为

a1, a1+a2, a1+a2+a3.......a1+a2+...ak

求和之后变为 a1 *k + a2 * (k - 1) + a3 * (k - 2).... + ak

 #include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stdlib.h>
#define INF 0xfffffff
#define N 55
#define M 2555
using namespace std;
int w[N][M],n,m,p,lx[N],d,ly[M],link[M],x[N],y[M];
bool match(int u)
{
x[u] = ;
for(int i = ; i <= p ; i++)
{
if(y[i]) continue;
int o = lx[u]+ly[i]-w[u][i];
if(o==)
{
y[i] = ;
if(!link[i]||match(link[i]))
{
link[i] = u;
return true;
}
}
else if(o<d) d = o;
}
return false;
}
void km()
{
int i,j;
for(i = ;i <= n ;i++)
lx[i] = -INF;
memset(ly,,sizeof(ly));
memset(link,,sizeof(link));
for(i = ; i <= n ;i++)
for(j = ; j <= p ;j++)
lx[i] = max(lx[i],w[i][j]);
for(i = ; i <= n ;i++)
{
for(;;)
{
d = INF;
memset(x,,sizeof(x));
memset(y,,sizeof(y));
if(match(i)) break;
for(j = ;j <= n ;j++) if(x[j]){lx[j]-=d;}
for(j = ;j <= p ;j++) if(y[j]){ly[j]+=d;}
}
}
}
int main()
{
int cas,i,j,k,a;
cin>>cas;
while(cas--)
{
scanf("%d%d",&n,&m);
for(i = ;i <= n ;i++)
for(j = ;j <= m ; j++)
{
scanf("%d",&a);
for(k = ; k <= n ;k++)
w[i][(j-)*n+k] = -*k*a;
}
p = n*m;
double s=;
km(); for(i = ;i <= p ; i++)
if(link[i])
{
s-=w[link[i]][i];
}
printf("%.6f\n",1.0*s/n);
}
return ;
}