zoukankan      html  css  js  c++  java
  • poj 3436 ACM Computer Factory 最大流+记录路径

    题目

    题意:

    每一个机器有一个物品最大工作数量,还有一个对什么物品进行加工,加工后的物品是什么样。给你无限多个初始都是000....的机器,你需要找出来经过这些机器操作后最多有多少成功的机器(111.....)

    题解:

    st是网络流起始点,en是终止点

    首先肯定是要拆点的,因为题目上给出的是每一个机器的最大加工数量。这是对于机器本身,所以拆点之后i->start和i->last这条边的容量就是机器的最大加工数量

    这个题的话建图很清晰,只要它要加工的原始物品是000...类型的,它就可以和st建一条边,容量无限大。如果加工后的物品是111...这种类型的,那么就可以让这个i->last和en建一条边,容量都是无限大

    之后的话如果某个机器加工后的产品可以作为某个机器的原料,那就让他们之间连一条容量无限大的边。这里要注意,当某个机器接受的原料某个部件为2,那这个位置有没有部件都可以连边

    例:1机器原料为1 2 1,那么1 0 1和1 1 1的产品他都可以接收

    因为题目要求最后要输出那两个机器之间有流量,所以只要跑完最大流之后一个一个点的去检查。发现这个点和其他点之间有流量,那就出输出它.因为在跑最大流的过程中如果找到一条增广路,那么这条可行路上所有边的流量都要减少,就是通过这一点来判断的(具体看代码)

    代码:

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <vector>
      6 #include <queue>
      7 #define INF 99999999
      8 using namespace std;
      9 const int N = 150;
     10 int p,n,cnt;
     11 int capacity[N],m[N][N],head[N],cur[N],d[N];
     12 
     13 struct edge
     14 {
     15     int u,v,c,flow,next;
     16 } e[N*N];
     17 struct shudui
     18 {
     19     int u,v,w;
     20 }que[N*N];
     21 void adde(int u,int v,int w,int f)
     22 {
     23     e[cnt].v=v;
     24     e[cnt].u=u;
     25     e[cnt].c=w;
     26     e[cnt].flow=f;
     27     e[cnt].next=head[u];
     28     head[u]=cnt++;
     29 }
     30 bool bfs(int s,int t)
     31 {
     32     for(int i=0; i<=2*n+2; i++) d[i]=0;
     33     d[s]=1;
     34     queue <int > q;
     35     q.push(s);
     36     while(!q.empty())
     37     {
     38         int u=q.front();
     39         q.pop();
     40         for(int i=head[u]; i!=-1; i=e[i].next)
     41         {
     42             int v=e[i].v;
     43             if(!d[v] && e[i].c>e[i].flow)
     44             {
     45                 d[v]=d[u]+1;
     46                 q.push(v);
     47             }
     48         }
     49     }
     50     return d[t]!=0;
     51 }
     52 int dfs(int s,int a)
     53 {
     54     if(s==2*n+1 || a==0) return a;
     55     int flow = 0;
     56     for(int &i=cur[s]; i!=-1; i=e[i].next)
     57     {
     58         int v=e[i].v,f;
     59         if(d[v]!=d[s]+1) continue ;
     60         f=dfs(v,min(a,e[i].c-e[i].flow));
     61         if(f)
     62         {
     63             e[i].flow+=f;
     64             e[i^1].flow-=f;
     65             a-=f;
     66             flow+=f;
     67             if(a==0) break;
     68         }
     69     }
     70     if(!flow) d[s]=-1;
     71     return flow;
     72 }
     73 int main()
     74 {
     75     scanf("%d%d",&p,&n);
     76     memset(head,-1,sizeof(head));
     77     for(int i=1; i<=n; i++)
     78     {
     79         scanf("%d",&capacity[i]);
     80         for(int j=1; j<=2*p; j++) scanf("%d",&m[i][j]);
     81     }
     82 
     83     for(int i=1; i<=n; i++)
     84     {
     85         adde(i,i+n,capacity[i],0);
     86         adde(i+n,i,0,0);
     87         int flag1=1,flag2=1;
     88         for(int j=1; j<=p; j++)
     89         {
     90             if(m[i][j]==1) flag1=0;
     91             if(m[i][j+p]!=1) flag2=0;
     92         }
     93         if(flag1) adde(0,i,INF,0),adde(i,0,0,0);
     94         if(flag2) adde(i+n,2*n+1,INF,0),adde(2*n+1,i+n,0,0);
     95     }
     96     for(int i=1; i<=n; i++)
     97     {
     98         for(int j=1; j<=n; j++)  //这里j的初始值不能是i+1,卧槽!!
     99         {
    100             if(i==j) continue ;
    101             bool ok = true ;
    102             for(int k=p+1; k<=p*2; k++)
    103             {
    104                 int now = k-p;
    105                 if(m[j][now]==2) continue ;
    106                 if(m[i][k]!=m[j][now]) ok=false;
    107             }
    108             if(ok)
    109             {
    110                 adde(i+n,j,INF,0);
    111                 adde(j,i+n,0,0);
    112             }
    113         }
    114     }
    115     int max_flow = 0;
    116     while(bfs(0,2*n+1))
    117     {
    118         for(int i=0; i<=2*n+1; i++) cur[i]=head[i];
    119         max_flow+=dfs(0,INF);
    120     }
    121     printf("%d ",max_flow);
    122     int ans=0;
    123     for(int i=1+n; i<=2*n; i++)  //如果两个点之间有合作关系,那么他们的e[j].flow肯定不会为0,就是利用这一点找出来所有有合作关系的
    124     {  //点。题目没有要求怎么输出,那就随便输出就可以
    125         for(int j=head[i]; j!=-1; j=e[j].next)
    126         {
    127             int v=e[j].v;
    128             if(v!=2*n+1 && v!=0 && e[j].flow && v!=i-n)
    129             {
    130                 que[ans].u=i-n;
    131                 que[ans].v=v;
    132                 que[ans].w=e[j].flow;
    133                 ans++;
    134             }
    135         }
    136     }
    137     printf("%d
    ",ans);
    138     for(int i=0;i<ans;++i)
    139     {
    140         printf("%d %d %d
    ",que[i].u,que[i].v,que[i].w);
    141     }
    142     return 0;
    143 }
    View Code
  • 相关阅读:
    静下来好好学习
    深入学习Redis主从复制
    深入学习Redis持久化
    TPS、并发用户数、吞吐量关系
    P1067 多项式输出
    P1014 Cantor表
    P2089 烤鸡
    P1579 哥德巴赫猜想(升级版)
    P1217 [USACO1.5]回文质数 Prime Palindromes
    校内比赛 城市交通费
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11781544.html
Copyright © 2011-2022 走看看