Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 5412 | Accepted: 2268 |
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个车间,每个任务在不同的车间内完成花费的时间不同,且每个车间只能完成一个任务后才能接下一个任务,求完成所有任务的最小平均时间。
思路:最小费用最大流,拆点将m个车间都拆成n个,,表示第i个任务在第j个车间的第k个时间段完成。建图时,把每个任务看做一个源点,将其连向每个时间段的点,权值为经过累积计算后的花费,容量为1,矩阵中的每个点连向超级汇点,容量为1,花费为0,表示这个这件在这个时候只能使用一次,同时加入超级源点,将其连向每个任务,容量为1,花费为0。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
#define MAXN 100100
#define MAXM 1000100
int vis[MAXN],d[MAXN],pre[MAXN],aa[MAXN];
struct Edge
{
int u, v, c, cost, next;
} edge[MAXM];
int s[MAXN], cnt;
void init()
{
cnt = 0;
memset(s, -1, sizeof(s));
}
void add(int u, int v, int c, int cost)
{
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].cost = cost;
edge[cnt].c = c;
edge[cnt].next = s[u];
s[u] = cnt++;
edge[cnt].u = v;
edge[cnt].v = u;
edge[cnt].cost = -cost;
edge[cnt].c = 0;
edge[cnt].next = s[v];
s[v] = cnt++;
}
bool spfa(int ss, int ee,int &flow,int &cost)
{
queue<int> q;
memset(d, INF, sizeof d);
memset(vis, 0, sizeof vis);
d[ss] = 0, vis[ss] = 1, pre[ss] = 0, aa[ss] = INF;
q.push(ss);
while (!q.empty())
{
int u = q.front();
q.pop();
vis[u] = 0;
for (int i = s[u]; ~i; i = edge[i].next)
{
int v = edge[i].v;
if (edge[i].c>0&& d[v]>d[u] + edge[i].cost)
{
d[v] = d[u] + edge[i].cost;
pre[v] = i;
aa[v] = min(aa[u], edge[i].c);
if (!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
if (d[ee] == INF) return 0;
flow += aa[ee];
cost += d[ee]*aa[ee];
int u = ee;
while (u != ss)
{
edge[pre[u]].c -= aa[ee];
edge[pre[u] ^ 1].c += aa[ee];
u = edge[pre[u]].u;
}
return 1;
}
int MCMF(int ss, int ee)
{
int cost = 0, flow=0;
while (spfa(ss, ee, flow, cost));
return cost;
}
int main()
{
int T,n,m,u,v,c,x;
for(scanf("%d",&T); T--;)
{
init();
scanf("%d%d",&m,&n);
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++)
{
scanf("%d",&x);
for(int k=0; k<m; k++)
{
add(i,m+j+k*n,1,x*(k+1));
}
}
for(int i=1;i<=m;i++)
add(0,i,1,0);
for(int j=1;j<=n;j++)
for(int k=0; k<m; k++)
{
add(m+j+k*n,100000,1,0);
}
printf("%.6f\n",MCMF(0,100000)*1.0/m);
}
return 0;
}