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;
}

原文地址:https://www.cnblogs.com/lvpengms/p/1796811.html