• 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
    ",res,ans.size());
        for(int i=0;i<ans.size();i++){
            printf("%d %d %d
    ",ans[i].u,ans[i].v,ans[i].cap);
        }
        }
        return 0;
    }
  • 相关阅读:
    基础学习笔记之opencv(9):Mat图像扫描
    Android开发历程_7(ListView和ProgressBar控件的学习)
    基础学习笔记之opencv(13):基本绘图
    Qt学习之路_5(Qt TCP的初步使用)
    基础学习笔记之opencv(7):ubuntu下opencv在Qt中的使用
    EM算法学习笔记_1(对EM算法的简单理解)
    Android开发历程_1(从1个activity跳转到另一个activity)
    Matlab成长之路_1(图片,视频,摄像头的读取和显示)
    深入理解JavaScript系列(41):设计模式之模板方法
    深入理解JavaScript系列(44):设计模式之桥接模式
  • 原文地址:https://www.cnblogs.com/IKnowYou0/p/6789144.html
Copyright © 2020-2023  润新知