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\n",ans);
138     for(int i=0;i<ans;++i)
139     {
140         printf("%d %d %d\n",que[i].u,que[i].v,que[i].w);
141     }
142     return 0;
143 }
View Code

 

posted @ 2019-11-02 13:54  kongbursi  阅读(133)  评论(0编辑  收藏  举报