现在的位置: 首页 > 综合 > 正文

poj 3686 The Windy’s(最小费用最大流)

2017年12月13日 ⁄ 综合 ⁄ 共 1757字 ⁄ 字号 评论关闭

题意:有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;
}

抱歉!评论已关闭.