poj3426(网络流)

题意:有n个机器加工计算机,有p个计算机零件,接下来输出n个机器加工计算机情况,2*p+1个数据,第一个是每小时最多生产计算机台数,接下来p个数是,可以从p个零件状态的计算机生产到后面p个零件状态的计算机。问最多一小时生产多少计算机。

当然这里零件状态是这样定义的,0表示没有,1表示必须要,2表示可有可无(所以2可以无视)

 

思路:

当然是从零件全是0的计算机开始了。然而你忘了有2也是可以的,只要零件非1就行。(一个坑点)

会想到有很多可以加工全非1的机器,和加工到全1的机器,那么就是一个多源点,多汇点的网络流,就要用一个超级源点,超级汇点。

超级源点连接可以从零件全非1开始加工的机器,而可以加工到全为1的机器连接超级汇点(第一步

 

那么下一步就是连接机器,看是否加工的半成品是否可以给下一个机器加工。只要每个零件对应不能同时一个0,一个1,即可。(第二步

 

接下来就是求网络流最大流量了,这里用dinic算法模板就行。(第三步

最后只要计算有流量的路径并输出即可。(最后一步

最后想复杂了,以为要输出每条增广路径,最后wa了几发。。。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
struct node{
    int c,f;
}mp[100][100];
int sx,ex,n,m,cnt;
int g[100][100];
int step[100],ans,li,outline[100][5];
//li记录流量路径条数,outline记录路径情况 

bool bfs()//dinic--求层次网络 
{
    memset(step,0,sizeof(step));
    step[sx]=1;
    queue<int> q;
    q.push(sx);
    while(!q.empty())
    {
        int p=q.front();
        q.pop();
        for(int i=0;i<=m+1;i++)
        {
            if(!step[i]&&mp[p][i].c-mp[p][i].f)
            {
                step[i]=step[p]+1;
                q.push(i);
            }
        }
    }
    return step[ex]!=0;
}

int dinic(int pos,int flow)//求出层次网络中所有增广路径流量 
{
    int f=flow;
    if(pos==ex)
        return flow;
    for(int i=0;i<=m+1;i++)
    {
        if(mp[pos][i].c-mp[pos][i].f&&step[pos]+1==step[i])
        {
            int a=mp[pos][i].c-mp[pos][i].f;
            int t=dinic(i,min(a,flow));
            mp[pos][i].f+=t;
            mp[i][pos].f-=t;
            flow-=t;
        }
    }
    return f-flow;
}

void solve()//最大流 
{
    while(bfs())
    {
        ans+=dinic(sx,inf);
    }
    return ;
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(mp,0,sizeof(mp));
        sx=0,ex=m+1;//起点sx,终点ex 
        ans=0,li=0;
        for(int i=1;i<=m;i++)
            for(int j=0;j<=2*n;j++)
                scanf("%d",&g[i][j]);
        for(int i=1;i<=m;i++)//判断是否可以连接超级源点或超级汇点 
        {
            int flag1=0,flag2=0;
            for(int j=1;j<=n;j++)
            {
                if(g[i][j]==1)
                    flag1=1;
                if(g[i][j+n]==0)
                    flag2=1;
            }
            if(!flag1)//连接超级源点 
                mp[sx][i].c=g[i][0];
            if(!flag2)//连接超级汇点 
                mp[i][ex].c=g[i][0];
        }
        for(int i=1;i<=m;i++)//判断是否可以两两工厂相连 
        {
            for(int j=1;j<=m;j++)
            {
                if(i==j)
                    continue;
                int flag=0;
                for(int k=1;k<=n;k++)
                {
                    if(g[i][k+n]+g[j][k]==1)
                    {
                        flag=1;
                        break;
                    }
                }
                if(flag)
                    continue;
                mp[i][j].c=min(g[i][0],g[j][0]);
            }
        }
        solve();//求最大流 
        for(int i=1;i<=m;i++)//判断路是否有流量 
        {
            for(int j=1;j<=m;j++)
            {
                if(mp[i][j].f>0)
                {
                    li++;
                    outline[li][1]=i;
                    outline[li][2]=j;
                    outline[li][3]=mp[i][j].f;
                }
            }
        }
        cout<<ans<<' '<<li<<endl;
        for(int i=1;i<=li;i++)
        {
            cout<<outline[i][1]<<' '<<outline[i][2]<<' '<<outline[i][3]<<endl;
        }
    }
    return 0;
}

 

posted @ 2019-07-05 19:17  怀揣少年梦.#  阅读(210)  评论(0编辑  收藏  举报