poj 3686 The Windy's
来源:互联网 发布:linux安装ha 编辑:程序博客网 时间:2024/04/29 12:03
一开始把图建错了。结果纠结到现在。本题需要拆点,把每台机器当成n台使用。由于每台机器之前加工的玩具无法确定,但是我们可以反过来想。假设当前这个玩具倒数第K加工,那么他和后面加工的玩具总共延误K*MAP[I][J],我们就可以根据这个来建图。然后套KM算法去做。#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#define inf 1000001int map[55][2500],visx[55],visy[2500],link[2500],lx[55],ly[2500],xx[55][2500];double sum;int n,m,x,t;bool dfs(int i){ visx[i]=1; for(int j=1;j<=m*n;j++) { if(visy[j]==0&&lx[i]+ly[j]-map[i][j]==0) { visy[j]=1; if(link[j]==-1||dfs(link[j])) { link[j]=i; return true; } } }return false;}void km(){ for(int i=1;i<=n;i++) { lx[i]=-inf; for(int j=1;j<=n*m;j++) lx[i]=max(lx[i],map[i][j]); } memset(ly,0,sizeof(ly)); memset(link,-1,sizeof(link)); for(int i=1;i<=n;i++) { while(1) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(dfs(i)) break; int d=inf; for(int j=1;j<=n;j++) { if(visx[j]==1) for(int k=1;k<=m*n;k++) if(visy[k]==0) d=min(d,lx[j]+ly[k]-map[j][k]); } for(int j=1;j<=n;j++) if(visx[j]==1) lx[j]-=d; for(int j=1;j<=n*m;j++) if(visy[j]==1) ly[j]+=d; } }} int main(){ scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); sum=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&xx[i][j]); } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=m;k++) { map[i][(k-1)*n+j]=-j*xx[i][k]; } km(); for(int i=1;i<=n*m;i++) { if(link[i]!=-1) sum+=map[link[i]][i]; } printf("%.6lf\n",-1*sum/n); }return 0;}