POJ3436 ACM Computer Factory

为了追求 ACM 比赛的公平性,所有用作 ACM 比赛的电脑性能是一样的,而 ACM 董事会专门有一条生产线来生产这样的电脑,随着比赛规模的越来越大,生产线的生产能力不能满足需要,所以说 ACM 董事会想要重新建造一条生产线。 生产线是全自动化的,所以需要机器来组成生产线,给定有多少种机器,标准 ACM 用电脑有多少部份,每种机器将什么样的 ACM 电脑半成品处理成什么样的电脑半成品(对于输入的电脑半成品,每部分有 0,1,2 三种状态:代表着 0、这部分必须没有我才能处理,1、这部分必须有我才能处理,2、这部分有没有我都能处理。对于输出的电脑半成品有 0,1 两种状态:代表着 0,处理完后的电脑半成品里没有这部分,1、处理完的电脑半成品有这部分),每一个机器每小时可以处理 Q 个半成品(输入数据中的 Qi)。 求组装好的成产线的最大工作效率(每小时最多生成多少成品,成品的定义就是所有部分的状态都是“1”) 第一行输入两个数:一个 P 代表有 P 个零件, 一个 N 代表有 N 台机器。 接下来N 行,每行第一个数字有 Qi,代表 第 i 个零件每小时能加工的半成品零件个数。然后是 2*P 个数字,前 P 个数字是加工前半成品需要满足的条件,后 P 个数表示加工后的半成品的数量。
 
用网络流解决工厂流水线的问题并保存路径。每台机器都有容量,所以把一台机器分成两个点,中间建一条容量的边。同时如果一台机器的输出符合另一台机器的输入,则建一条容量无穷大的边。同时要增加源点和汇点,输入没有 1 的连接源点,输出全是 1 的连接
汇点
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1014;
const int inf=1e9;
int g[maxn][maxn];
int backup[maxn][maxn];
int pre[maxn];
int flow[maxn];
int Line[maxn][3];
int in[maxn][maxn];
int maxflow;
int N,M;
queue<int> q;
void init () {
    while (!q.empty()) q.pop();
    fill (pre,pre+maxn,0);
    fill (flow,flow+maxn,0);
    maxflow=0;
    for (int i=0;i<maxn;i++)
    for (int j=0;j<maxn;j++)
    g[i][j]=0;
} 
int bfs (int s,int t) {
    while (!q.empty()) q.pop();
    for (int i=0;i<=N;i++) pre[i]=-1;
    pre[s]=0;
    q.push(s);
    flow[s]=inf;
    while (!q.empty()) {
        int x=q.front();
        q.pop();
        if (x==t) break;
        for (int i=0;i<=N;i++) {
            if (g[x][i]!=0&&pre[i]==-1) {
                pre[i]=x;
                flow[i]=min(flow[x],g[x][i]);
                q.push(i);
            }
        }
    }
    if (pre[t]==-1) return -1;
    else return flow[t];
}
void Edmonds_Karp (int s,int t) {
    int increase=0;
    while ((increase=bfs(s,t))!=-1) {
        int k=t;
        while (k!=s) {
            int last=pre[k];
            g[last][k]-=increase;
            g[k][last]+=increase;
            k=last;
        }
        maxflow+=increase;
    }
}
int main () {
    int n,p;
    while (~scanf("%d %d",&p,&n)) {
        init ();
        for (int i=1;i<=n;i++) {
            for (int j=0;j<2*p+1;j++)
            scanf ("%d",&in[i][j]);
        }
        for (int i=1;i<=n;i++)
        g[2*i-1][2*i]=in[i][0];
        N=2*n+1;
        for (int i=1;i<=n;i++) {
            bool flag_s=true;
            bool flag_t=true;
            for (int j=0;j<p;j++) {
                if (in[i][j+1]==1) flag_s=false;
                if (in[i][j+1+p]==0) flag_t=false;
            }
            if (flag_s) g[0][2*i-1]=inf;
            if (flag_t) g[2*i][N]=inf;
            for (int j=1;j<=n;j++) {
                if (i!=j) {
                    bool flag=true;
                    for (int k=0;k<p;k++) 
                    if ((in[i][k+p+1]==0&&in[j][k+1]==1)||(in[i][k+p+1]==1&&in[j][k+1]==0)) {
                        flag=false;
                        break;
                    }
                    if (flag) g[2*i][2*j-1]=min(in[i][0],in[j][0]);
                }
            }
        }
        memcpy (backup,g,sizeof(g));
        Edmonds_Karp (0,N);
        printf ("%d ",maxflow);
        int ans=0;
        for (int i=1;i<=n;i++) {
            for (int j=1;j<=n;j++) {
                if (g[2*i][2*j-1]<backup[2*i][2*j-1]) {
                    Line[ans][0]=i;
                    Line[ans][1]=j;
                    Line[ans][2]=backup[2*i][2*j-1]-g[2*i][2*j-1];
                    ans++;
                }
            }
        }
        printf ("%d\n",ans);
        for (int i=0;i<ans;i++)
        printf ("%d %d %d\n",Line[i][0],Line[i][1],Line[i][2]);
    }
    return 0;
}

 

posted @ 2020-02-16 11:02  zlc0405  阅读(94)  评论(0编辑  收藏  举报