• POJ 3436 ACM Computer Factory (拆点+最大流)


    题意:有n机器要加工部件,每个部件有p个零件,机器加工部件的速度已知,而且其所加工的部件满足机器的要求,0表示这个零件不能有,1表示这个零件必须有,2表示无所谓,又知道一个机器加工后这个部件的组成,问这n台机器一定时间内最多能叫加工多少部件,即部件的状态时从00...0 到11...1?

    思路:开始大体上感觉是最大流,以前也做过差不多的题目,因为题中对机器的加工速度进行的限制,那么建立流网络时最通用的做法就是拆点,把x拆成a->b,边容量就是机器的速度,那么在这个基础上进行构图就方便多了,因为题中还要求输出流网络,所以在边结构体上EDGE加点信息就可以很方便的输出流量了,注意机器间连接的关系,不能搞混!

    PS:容易出错的地方discuss都有了,我还WA了2次,原来是把流量为0的边也输出了......

    #include <iostream>
    #include
    <cstdio>
    #include
    <algorithm>
    #include
    <memory.h>
    #include
    <cmath>
    #include
    <bitset>
    #include
    <queue>
    #include
    <vector>
    using namespace std;

    const int BORDER = (1<<20)-1;
    const int MAXSIZE = 37;
    const int MAXN = 2200;
    const int INF = 0x4ffffff;

    #define CLR(x,y) memset(x,y,sizeof(x))
    #define ADD(x) x=((x+1)&BORDER)
    #define IN(x) scanf("%d",&x)
    #define OUT(x) printf("%d\n",x)
    #define MIN(m,v) (m)<(v)?(m):(v)
    #define MAX(m,v) (m)>(v)?(m):(v)
    #define ABS(x) ((x)>0?(x):-(x))

    int index,s,t,nv,net[MAXN];
    int ans,p,n;
    int start[12],end[12];
    int res[MAXN*MAXN][3];

    typedef
    struct{
    int val;
    int in[12];
    int out[12];
    }NODE;
    typedef
    struct{
    int next,pair;
    int v,cap,flow;
    int a,b;
    }EDGE;
    EDGE edge[MAXN
    *MAXN];
    NODE node[MAXN];
    /* 检查a是否可以被b相容 */
    bool _check(int* a, int* b)
    {
    for(int i = 0; i < p; ++i)
    if(1 == a[i]+b[i])
    return false;
    return true;
    }
    int init()
    {
    CLR(net,
    -1);
    CLR(start,
    0);
    for(int i = 0; i <= p; ++i)
    end[i]
    = 1;
    index
    = 0;
    ans
    = 0;
    return 0;
    }
    int input()
    {
    int i,j,tmp;
    for(i = 1; i <= n; ++i)
    {
    scanf(
    "%d",&node[i].val);
    for(j = 0; j < p; ++j)
    scanf(
    "%d",&(node[i].in[j]));
    for(j = 0; j < p; ++j)
    scanf(
    "%d",&(node[i].out[j]));
    }
    return 0;
    }
    void add_edge(const int& u,const int& v,const int& val,const int& aa,const int& bb)
    {
    edge[index].next
    = net[u];
    net[u]
    = index;
    edge[index].v
    = v;
    edge[index].a
    = aa;
    edge[index].b
    = bb;
    edge[index].cap
    = val;
    edge[index].flow
    = 0;
    edge[index].pair
    = index+1;
    ++index;
    edge[index].next
    = net[v];
    net[v]
    = index;
    edge[index].a
    = -1;
    edge[index].b
    = -1;
    edge[index].v
    = u;
    edge[index].cap
    = 0;
    edge[index].flow
    = 0;
    edge[index].pair
    = index - 1;
    ++index;
    }
    int make_graph()
    {
    int i,j,u,v,tmp;
    s
    = 2*n + 1;
    t
    = 2*n + 2;
    nv
    = t;
    // s --> x
    for(i = 1; i <= n; ++i)
    if(_check(start,node[i].in))
    add_edge(s,i,INF,
    -1,-1);
    // x --> t
    for(i = 1; i <= n; ++i)
    if(_check(node[i].out,end))
    add_edge(i
    +n,t,INF,-1,-1);
    // x --> y
    for(i = 1; i <= n; ++i)
    for(j = 1; j <= n;++j)
    {
    if(i == j)
    continue;
    else
    {
    if(_check(node[i].out,node[j].in))
    add_edge(i
    +n,j,INF,i,j);
    }
    }
    // x --> x
    for(i = 1; i <= n; ++i)
    add_edge(i,i
    +n,node[i].val,-1,-1);
    return 0;
    }
    int ISAP()
    {
    long numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];
    long cur_flow,max_flow,u,tmp,neck,i;
    memset(dist,
    0,sizeof(dist));
    memset(numb,
    0,sizeof(numb));
    for(i = 1 ; i <= nv ; ++i)
    curedge[i]
    = net[i];
    numb[nv]
    = nv;
    max_flow
    = 0;
    u
    = s;
    while(dist[s] < nv)
    {
    /* first , check if has augmemt flow */
    if(u == t)
    {
    cur_flow
    = INF;
    for(i = s; i != t;i = edge[curedge[i]].v)
    {
    if(cur_flow > edge[curedge[i]].cap)
    {
    neck
    = i;
    cur_flow
    = edge[curedge[i]].cap;
    }
    }
    for(i = s; i != t; i = edge[curedge[i]].v)
    {
    tmp
    = curedge[i];
    edge[tmp].cap
    -= cur_flow;
    edge[tmp].flow
    += cur_flow;
    tmp
    = edge[tmp].pair;
    edge[tmp].cap
    += cur_flow;
    edge[tmp].flow
    -= cur_flow;
    }

    max_flow
    += cur_flow;
    u
    = s;
    }
    /* if .... else ... */
    for(i = curedge[u]; i != -1; i = edge[i].next)
    if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1)
    break;
    if(i != -1)
    {
    curedge[u]
    = i;
    pre[edge[i].v]
    = u;
    u
    = edge[i].v;
    }
    else{
    if(0 == --numb[dist[u]]) break;
    curedge[u]
    = net[u];
    for(tmp = nv,i = net[u]; i != -1; i = edge[i].next)
    if(edge[i].cap > 0)
    tmp
    = tmp<dist[edge[i].v]?tmp:dist[edge[i].v];
    dist[u]
    = tmp + 1;
    ++numb[dist[u]];
    if(u != s) u = pre[u];
    }
    }
    return max_flow;
    }
    int output()
    {
    int i,j,u,v,cnt;
    cnt
    = 0;
    for(i = 0; i < index; ++i)
    {
    u
    = edge[i].a;
    v
    = edge[i].b;
    if(u != v && edge[i].flow > 0)
    {
    res[cnt][
    0] = u;
    res[cnt][
    1] = v;
    res[cnt][
    2] = edge[i].flow;
    ++cnt;
    }
    }
    printf(
    "%d %d\n",ans,cnt);
    for(i = 0; i < cnt; ++i)
    printf(
    "%d %d %d\n",res[i][0],res[i][1],res[i][2]);
    printf(
    "\n");
    return 0;
    }

    int work()
    {
    make_graph();
    ans
    = ISAP();
    return 0;
    }
    int main()
    {
    while(scanf("%d%d",&p,&n)!=EOF)
    {
    init();
    input();
    work();
    output();
    }
    return 0;
    }

  • 相关阅读:
    Java自学-多线程 常见线程方法
    Java自学-多线程 启动一个线程
    Java自学-Lambda 聚合操作
    Java自学-Lambda 方法引用
    Java自学-Lambda 概念
    Java自学-泛型 泛型转型
    Java自学-泛型 通配符
    Java自学-泛型 支持泛型的类
    <VCC笔记> 关于Assertion
    <VCC笔记>VCC简介与安装
  • 原文地址:https://www.cnblogs.com/lvpengms/p/1796811.html
Copyright © 2020-2023  润新知