poj3686 The Windy's

The Windy's
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 5733   Accepted: 2369

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

Source

题目大意:n个玩具在m个工厂内加工,给出每个玩具在不同工厂加工所用的时间,一个工厂在任意时刻内最多只能加工一个玩具,求所有玩具的最小平均等待时间.
分析:复杂的匹配问题(指派问题).要求最小化所有玩具的平均等待时间其实只需要最小化所有玩具的等待时间.
          只考虑一个工厂,如果该工厂加工3个玩具,那么总等待时间就是a1 * 3 + a2 * 2 + a3*3,每个玩具的加工时间前都会有一个系数.那么可以考虑将工厂拆点(加工了k-1个玩具,当前加工第k个玩具),那么对应的玩具加工时间*k就是对答案的贡献了,最后求一下最小费用最大流就可以了.
          坑点:1.编号问题需要注意. 2.会有多达n*m+n+1个点,连边的数量会上30w,数组要适当开大.  3.多次清空vis数组会T掉,用时间戳优化.
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 100010,inf = 0x3f3f3f3f;
int head[maxn],to[maxn],nextt[maxn],w[maxn],c[maxn],tot = 2;
int t,n,m,S,T,ans,d[maxn],vis[maxn],vis2[maxn];
int dfs_clock,dfs_clock2;

void init()
{
    memset(head,0,sizeof(head));
    tot = 2;
    ans = 0;
    dfs_clock = dfs_clock2 = 0;
}

void add(int x,int y,int z,int p)
{
    c[tot] = p;
    w[tot] = z;
    to[tot] = y;
    nextt[tot] = head[x];
    head[x] = tot++;

    c[tot] = -p;
    w[tot] = 0;
    to[tot] = x;
    nextt[tot] = head[y];
    head[y] = tot++;
}

bool spfa()
{
    queue <int> q;
    memset(d,inf,sizeof(d));
    dfs_clock++;
    dfs_clock2++;
    d[S] = 0;
    vis[S] = dfs_clock;
    q.push(S);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = 0;
        for (int i = head[u];i;i = nextt[i])
        {
            int v = to[i];
            if (w[i] && d[v] > d[u] + c[i])
            {
                d[v] = d[u] + c[i];
                if (vis[v] != dfs_clock)
                {
                    vis[v] = dfs_clock;
                    q.push(v);
                }
            }
        }
    }
    return d[T] < inf;
}

int dfs(int u,int f)
{
    if (u == T)
    {
        ans += f * d[T];
        return f;
    }
    int res = 0;
    vis2[u] = dfs_clock2;
    for (int i = head[u];i;i = nextt[i])
    {
        int v = to[i];
        if (vis2[v] != dfs_clock2 && w[i] && d[v] == d[u] + c[i])
        {
            int temp = dfs(v,min(f - res,w[i]));
            res += temp;
            w[i] -= temp;
            w[i ^ 1] += temp;
            if (res == f)
                return res;
        }
    }
    return res;
}

void dinic()
{
    while (spfa())
        dfs(S,inf);
}

int main()
{
    scanf("%d",&t);
    while (t--)
    {
        init();
        scanf("%d%d",&n,&m);
        S = 0,T = m * n + n + 1;
        for (int i = 1; i <= n; i++)
            add(S,i,1,0);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
            {
                int tt;
                scanf("%d",&tt);
                for (int k = 1; k <= n; k++)
                    add(i,j * n + k,inf,tt * k);
            }
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                add(i * n + j,T,1,0);
        dinic();
        double anss = (double)ans / n;
        printf("%.6lf\n",anss);
    }

    return 0;
}

 

posted @ 2017-12-30 12:36  zbtrs  阅读(180)  评论(0编辑  收藏  举报