首页 > 代码库 > POJ 3436 ACM Computer Factory

POJ 3436 ACM Computer Factory

传送门:https://vjudge.net/problem/POJ-3436

技术分享

技术分享

技术分享

技术分享

题目大意:

每台电脑由p个零件组成,编号1~n。生产电脑完全由N台全自动的机器完成。每台机器能够添加一些零件和移除一些电脑零件。

用生产效率、输入规格、输出规格来描述每一台机器。

输入规格描述电脑必须具有那些零件,机器才能去加工它。这个输入规格由p个0,1,2整数的集合,0意味该零件必须不能存在,机器才能加工这个这台半成品电脑。相应的1是该零件必须存在,2是存在与否没有影响。

输出规格描述该半成品电脑经过该机器存在那些零件。这个输出规格是由0,1整数构成的集合,0意味着该办成品电脑,不具有该零件,1表示该电脑具有该零件。

 

问该工厂最大的生产效率是多少。


解题思路:

首先根据信息建图:

其中某个零件的组合方式有 00 01 02  10 11 12:

可以看出若组合中有01 10说明该机器不能连在一起。


耶耶耶,终于做对了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

const int MAXN=150;
const int INF=1<<20;

struct Machine{
    int flow;
    int in[15],out[15];
}mac[MAXN];

//检查该机器和源点之间是否有边
bool checkS(Machine a,int P){
    for(int i=0;i<P;i++)
        if(a.in[i]==1)
            return false;
    return true;
}

//检查该机器和汇点n+1之间是否有边
bool checkT(Machine a,int P){
    for(int i=0;i<P;i++)
        if(a.out[i]!=1)
            return false;
    return true;
}

//检查两个机器之间是否有边
bool checkEdge(Machine a,Machine b,int P){
    for(int i=0;i<P;i++)
        if(a.out[i]+b.in[i]==1)
            return false;
    return true;
}

struct Edge{
    int to,next;
    int init;
    int flow;
}edges[MAXN*10];


int head[MAXN];
int tot;
void init(){
    tot=0;
    memset(head,-1,sizeof(head));
}

void addEdge(int u,int v,int flow){
    edges[tot].to=v;
    edges[tot].flow=flow;
    edges[tot].init=flow;
    edges[tot].next=head[u];
    head[u]=tot++;
}

int level[MAXN];
bool makelevel(int s,int t ){
    memset(level,0,sizeof(level));
    level[s]=1;
    queue<int>q;
    q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        if(u==t) return true;
        for(int i=head[u];i!=-1;i=edges[i].next){
            int v=edges[i].to;
            if(!level[v]&&edges[i].flow){
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return false;
}

int DFS(int now,int maxf,int t){
    if(now==t) return maxf;
    int ret=0,f;
    for(int k=head[now];k!=-1;k=edges[k].next){
        int v=edges[k].to;
        if(edges[k].flow&&level[v]==level[now]+1){
            f=DFS(v,min(maxf-ret,edges[k].flow),t);
            edges[k].flow-=f;
            edges[k^1].flow+=f;
            ret+=f;
        }
        if(ret==maxf) return ret;
    }
    return ret;
}

int Dinic(int s,int t){
    int ans=0;
    while(makelevel(s,t))
        ans+=DFS(s,INF,t);
    return ans;
}

struct Node{
    int u;
    int v;
    int cap;
    Node(int u,int v,int cap):u(u),v(v),cap(cap){};
    Node(){};
};
 int main(){
    int P,N;
    while(scanf("%d%d",&P,&N)!=EOF){
    for(int i=1;i<=N;i++){
        scanf("%d",&mac[i].flow);
        for(int j=0;j<P;j++)
            scanf("%d",&mac[i].in[j]);
        for(int j=0;j<P;j++)
            scanf("%d",&mac[i].out[j]);
    }
    //下面是建图
    init();
    for(int i=1;i<=N;i++){
        if(checkS(mac[i],P)){    //这是检查该机器和源点0是否有边
            addEdge(0,i,mac[i].flow);
            addEdge(i,0,0);
        }
        if(checkT(mac[i],P)){  //这是检查该机器和汇点N+1是否有边
            addEdge(i,N+1,mac[i].flow);
            addEdge(N+1,i,0);
        }
        for(int j=1;j<=N;j++){   //这是检查机器i和机器j是否右边
            if(i==j) continue;
            if(checkEdge(mac[i],mac[j],P)){
                addEdge(i,j,mac[i].flow);
                addEdge(j,i,0);
            }
        }
    }

    int res=Dinic(0,N+1);
    vector<Node>ans;
    ans.clear();
    //如果最后残留网络的容量小于初始容量,说明该边是最大流走过的边
    for(int u=1;u<=N;u++){
        for(int j=head[u];j!=-1;j=edges[j].next){
            int v=edges[j].to;
            if(v>0&&v<=N&&edges[j].flow<edges[j].init){
                ans.push_back(Node(u,v,edges[j].init-edges[j].flow));
            }
        }
    }

    printf("%d %d\n",res,ans.size());
    for(int i=0;i<ans.size();i++){
        printf("%d %d %d\n",ans[i].u,ans[i].v,ans[i].cap);
    }
    }
    return 0;
}

 

POJ 3436 ACM Computer Factory