【二分图匹配入门专题1】poj3686 【km+思维建图】

本文介绍了一种解决玩具工厂订单调度问题的方法,通过构建一个n*m的矩阵来表示每个机器处理不同订单所需的时间,并利用匈牙利算法求解最小化平均完成时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                The Windy's

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

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值