A - ACM Computer Factory - poj 3436(最大流)

题 意:有一个ACM工厂会生产一些电脑,在这个工厂里面有一些生产线,分别生产不同的零件,不过他们生产的电脑可能是一体机,所以只能一些零件加工后别的生 产线才可以继续加工,比如产品A在生产线1号加工后继续前往生产线2号继续加工,直到成为完全产品。输入 P 意思是这个电脑需要P个零件,N表示有N个生产线,每个生产线都有最大加工量,并且需要什么零件和输出的是什么零件,0表示没有这个零件,1表示有这个零 件,2表示有没有都可以。
样例说明:
3 4
1号: 15  0 0 0 -->  0 1 0
2号: 10  0 0 0-->  0 1 1
3号: 30  0 1 2 -->  1 1 1
4号: 3   0 2 1  -->  1 1 1
1号生产线需要0 0 0这样的零件(这样的零件也就是无限制零件,源点),它可以把零件加工成 0 1 0 这个样子,然后 3 号生产线可以接受这种零件,并且加工成 1 1 1 也就是成品,到这样也就加工成功了,因为1号生产线每次可以加工 15 个零件,所以1->3的加工量就是 15,同理 2->3的加工量是 10,所以结果是 25。
 
分析:很明显的网络流题目,感觉难点应该在题目阅读和建图上.....可以用0当做源点 N+1当做汇点,然后每两点都进行匹配一些,看看是否可以连接,路径的权值为出点的生产能力。
 
注意:因为每个生产线的生产能力有限,所以需要拆点,防止超出他的生产能力,比如下图如果不拆点结果就会使20,实际上是10
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

const int oo=0x3f3f3f3f;

struct node
{
    int flow;
    int in[55];
    int out[55];
}a[20];

int maps[111][111];
int x[10005];int y[10005],z[10005];
int oldmaps[111][111];
int layer[111];
int p,n;

void init()
{
    memset(maps,0,sizeof(maps));
    memset(oldmaps,0,sizeof(oldmaps));
    for(int i=1;i<=p;i++)
    {
        a[1].in[i]=0;
        a[1].out[i]=0;
        a[n+2].in[i]=1;
        a[n+2].out[i]=1;
    }
    a[1].flow=oo;
    a[n+2].flow=oo;
}

int can(int x,int y)
{
    for(int i=1;i<=p;i++)
    {
        if(a[x].out[i]!=a[y].in[i]&&a[y].in[i]!=2)
            return 0;
    }
    return 1;
}

int bfs(int s,int End)
{
    memset(layer,0,sizeof(layer));
    queue<int>q;
    q.push(s);
    layer[s]=1;
    while(q.size())
    {
        s=q.front();
        q.pop();
        if(s==End)
        {
            return 1;
        }
        for(int i=1;i<=End;i++)
        {
            if(maps[s][i]&&layer[i]==0)
            {
                layer[i]=layer[s]+1;
                q.push(i);
            }
        }
    }

    return 0;
}

int dfs(int s,int End,int maxflow)
{
    if(s==End)
        return maxflow;

    int iflow=0;
    for(int i=1;i<=End;i++)
    {
        if(maps[s][i]>0&&layer[s]==layer[i]-1)
        {
            int flow=min(maxflow-iflow,maps[s][i]);
            flow=dfs(i,End,flow);
            maps[s][i]-=flow;
            maps[i][s]+=flow;

            iflow+=flow;
            if(maxflow==iflow)
                break;
        }
    }

    return iflow;
}

int Dinic()
{
    int max_flow=0;
    while(bfs(1,n*2))
    {
        max_flow+=dfs(1,n*2,oo);
    }
    return max_flow;
}

int main()
{
    while(~scanf("%d%d",&p,&n))
    {
        init();
        for(int i=2; i<=n+1; i++)
        {
            scanf("%d",&a[i].flow);
            for(int j=1; j<=p; j++)
            {
                scanf("%d",&a[i].in[j]);
            }
            for(int j=1;j<=p;j++)
            {
                scanf("%d",&a[i].out[j]);
            }
        }
        n+=2;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                {
                    oldmaps[i][j+n]=maps[i][j+n]=a[i].flow;
                }
                else
                {
                    if(can(i,j))
                        oldmaps[i+n][j]=maps[i+n][j]=min(a[i].flow,a[j].flow);
                    else
                        oldmaps[i+n][j]=maps[i+n][j]=0;
                }
            }
        }
        int sum=Dinic();

        int k=0;
        for(int i=2;i<n;i++)
        {
            for(int j=2;j<n;j++)
            {
                if(maps[i+n][j]<oldmaps[i+n][j])
                {
                    x[k]=i;y[k]=j;
                    z[k]=oldmaps[i+n][j]-maps[i+n][j];
                    k++;
                }
            }
        }
        printf("%d %d\n",sum,k);
        for(int i=0;i<k;i++)
            printf("%d %d %d\n",x[i]-1,y[i]-1,z[i]);
    }

    return 0;
}
/*
3 4
15  0 0 0  0 1 0
10  0 0 0  0 1 1
30  0 1 2  1 1 1
3   0 2 1  1 1 1
3 5
5   0 0 0  0 1 0
100 0 1 0  1 0 1
3   0 1 0  1 1 0
1   1 0 1  1 1 0
300 1 1 2  1 1 1
2 2
100  0 0  1 0
200  0 1  1 1
*/

 

posted @ 2015-09-16 18:41  梦中。。  阅读(185)  评论(0编辑  收藏  举报