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;}