题意:有n个任务需要用m台机器来完成,给出了第i个任务在第j个机器上需要花的时间。但是,每台机器一次只能工作一个任务,因此有些任务如果非要在某台机器上运行可能需要等待。求任务需要时间的最小平均值。
思路:第一眼看到感觉就是网络流问题,但没想到如何表示一台机器完成多个任务的时间如何表示。起初想到用标记边访问的次数来表示,细想是错的。。。。
思路:第一眼看到感觉就是网络流问题,但没想到如何表示一台机器完成多个任务的时间如何表示。起初想到用标记边访问的次数来表示,细想是错的。。。。
看了别人的想法,原来是用折点来表示。若某台机器按顺序执行k个任务,且k个任务的执行时间分别为t1,t2…tk,则k个任务的总的执行时间是t1*k+t2*(k-1)+t3*(k-2)+…+tk-1*2+tk。现在将机器拆点,拆成N个。第j个机器的第k个点表示该机器执行倒数第k个任务。连接该点的边的权值即为t[i][j]*k.以此构图后就可直接上模板了。
//5228K 938MS
#include <stdio.h>
#include <string.h>
const int inf = 0x3f3f3f3f;
const int VM = 50*50+60;
const int EM = (50*50*50+50+50*50)*2 + 10;
struct Edge
{
int to,nxt,cap,cost,re;
} edge[EM];
int head[VM],pre[VM],vedge[EM];
int ep,src,des;
void addedge (int cu,int cv,int cw,int co)
{
edge[ep].to = cv,edge[ep].cap = cw;
edge[ep].cost = co,edge[ep].re = ep+1;
edge[ep].nxt = head[cu],head[cu] = ep ++;
edge[ep].to = cu,edge[ep].cap = 0;
edge[ep].cost = -co,edge[ep].re = ep -1;
edge[ep].nxt = head[cv],head[cv] = ep ++;
}
int spfa()
{
int que[VM],vis[VM],dis[VM];
int i,front = 0,rear = 0;
memset (dis,0x3f,sizeof(dis));
memset (vis,0,sizeof(vis));
dis[src] = 0,que[rear++] = src;
while (front != rear)
{
int u = que[front ++];
front %= VM;
vis[u] = 0;
for (i = head[u]; i != -1; i = edge[i].nxt)
{
int v = edge[i].to;
if (edge[i].cap > 0&&dis[v]>dis[u]+edge[i].cost)
{
dis[v] = dis[u] + edge[i].cost;
pre[v] = i;
if (!vis[v])
{
que[rear++] = v;
rear %= VM;
vis[v] = 1;
}
}
}
}
if (dis[des] == inf)
return 0;
return 1;
}
int MaxMatch()
{
int res = 0;
while (spfa())
{
int u,k;
for (u = des; u != src; u = edge[edge[k].re].to)
{
k = pre[u];
edge[k].cap -= 1;
edge[edge[k].re].cap += 1;
res += edge[k].cost;
}
}
return res;
}
int main ()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int T,n,m,i,j,cc;
scanf ("%d",&T);
while (T --)
{
scanf ("%d%d",&n,&m);
memset (head,-1,sizeof(head));
ep = 0,src = 0,des = n+m*n+1;
for (i = 1; i <= n; i ++)
{
addedge (src,i,1,0);
for (j = 1; j <= m; j ++)
{
scanf ("%d",&cc);
for (int k = 1; k <= n; k ++)
{
addedge (i,n+(j-1)*n+k,1,cc*k);
if(i == 1)
addedge (n+(j-1)*n+k,des,1,0);
}
}
}
int ans = MaxMatch();
printf ("%.6lf\n",ans*1.0/n);
}
return 0;
}