您的位置:首页 > 其它

POJ3686 The Windy's

2014-08-03 13:47 399 查看

The Windy's

Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 3933 Accepted: 1688
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个任务,给出了每个任务在每个机器上完成的时间,求完成所有任务的平均时间最小。

完成任务的总时间就等于每个任务完成所需要的时间加上等待的时间,这题建图很好,要将任务拆点,建一个源点,从每个任务连一条边到任务,流量1,费用0,再将任务拆点,从任务i连一条边到n+(j-1)*n+k,表示任务i在机器j上被处理,k表示处理的次序,流量为1,费用k*mp[i][j],因为有可能有任务在这个机器上被处理,这个就表示等待的时间,最后再从被拆点的n的右边连一条边到汇点就行,然后跑一遍费用流就是答案了,这题点的个数n+n*m+2(n*m表示每个机器处理同一个任务的次序),边的个数n*m*n+n+n*m(n*m*n是任务i和n+(j-1)*n+k的边的个数),因为有反向边,所以还要*2.

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=3010;
const int MAXE=(2500*50+2500+50)*2;
const int INF=1<<30;
int head[MAXN],size;
struct EDGE
{
int v,next;
int cap;
int cost;
}edge[MAXE];
void init()
{
memset(head,-1,sizeof(head));
size=0;
}
void add_edge(int u,int v,int cap,int cost)
{
edge[size].v=v;
edge[size].cap=cap;
edge[size].cost=cost;
edge[size].next=head[u];
head[u]=size++;
edge[size].v=u;
edge[size].cap=0;
edge[size].cost=-cost;
edge[size].next=head[v];
head[v]=size++;
}
int dist[MAXN],pre[MAXN],pe[MAXN];
bool vis[MAXN];
bool spfa(int s,int t)
{
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
for(int i=0;i<=t+1;i++)
dist[i]=INF;
dist[s]=0;
vis[s]=1;
queue<int> q;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].cap&&dist[v]>dist[u]+edge[i].cost)
{
dist[v]=dist[u]+edge[i].cost;
pe[v]=i;
pre[v]=u;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
if(pre[t]==-1)
return 0;
return 1;
}
int max_flow;
int MCMF(int s,int t)
{
int min_cost=0;
max_flow=0;
while(spfa(s,t))
{
int aug=INF;
for(int v=t;v!=s;v=pre[v])
{
aug=min(aug,edge[pe[v]].cap);
}
max_flow+=aug;
min_cost+=aug*dist[t];
for(int v=t;v!=s;v=pre[v])
{
edge[pe[v]].cap-=aug;
edge[pe[v]^1].cap+=aug;
}
}
return min_cost;
}
int mp[55][55];
int main()
{
int t,n,m,i,j,k;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
int s=0,t=n+n*m+1;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&mp[i][j]);
}
}
for(i=1;i<=n;i++)
add_edge(s,i,1,0);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
for(k=1;k<=n;k++)
{
add_edge(i,n+(j-1)*n+k,1,mp[i][j]*k);   //i任务在机器j上第几个被处理
}
}
}
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
add_edge(n+(i-1)*n+j,t,1,0);
}
}
int ans=MCMF(s,t);
printf("%.6f\n",ans*1.0/n);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: