POJ 3436 ACM Computer Factory

解题思路: 首先添加两个超级节点S,E,分别表示起点和结点

  如果某个节点(i)不存在输入为1的条件,则添加一条S->i路径,容量为Qi;

  如果某个节点(j)输出全为1,则添加一条j->E路径,容量为Qj;

  如果节点i的输出与j的输入不存在冲突(输出与输入对应位置的和不能为1),则添加一条i->j的路径,容量为min(Qi, Qj).

代码实现:

代码
#include<iostream>
using namespace std;

#define MAX_VECT 60
#define INF 1e8
int c[MAX_VECT][MAX_VECT];
int n;
int maxflow(int s, int t)
{
int u, v, bg, ed, minflow, flow = 0;
int queue[MAX_VECT], pre[MAX_VECT];
while (true)
{
memset(pre,
-1, sizeof(pre));
for (queue[bg=ed=0]=s; bg <= ed; bg++)
{
u
= queue[bg];
for (int i = 0; (i < n)&&(pre[t]==-1); i++)
if (c[u][i] > 0 && pre[i] == -1)
{
pre[i]
= u;
queue[
++ed] = i;
}
}
if (pre[t] == -1)break;
minflow
= INF;
for (u = pre[v=t];v!=s;v=u,u=pre[v])
if (c[u][v] < minflow) minflow = c[u][v];
for (u = pre[v=t];v!=s;v=u,u=pre[v])
c[u][v]
-= minflow, c[v][u] += minflow;
flow
+= minflow;
}
return flow;
}

int main()
{
int In[55][25], G[MAX_VECT][MAX_VECT], Out[MAX_VECT][3];
int P, N, S, E, M, flow;
bool flag, flagE;
while (scanf("%d%d", &P, &N) == 2)
{
memset(c,
0, sizeof(c));
S
= N, E = N + 1;
n
= N + 2;
for (int i = 0; i < N; i++)
for (int j = 0; j < 2 * P + 1; j++)
scanf(
"%d", &In[i][j]);

for (int i = 0; i < N; i++)
{
flag
= flagE = true;
for (int k = 0; k < P; k++)
{
if(In[i][1 + k] == 1)flag = false;
if (In[i][P + 1 + k] == 0) flagE = false;
}
if (flag)c[S][i] = In[i][0];
if (flagE)c[i][E] = In[i][0];

flag
= true;
for (int j = 0; j < N; j++)
{
if (i != j)
{
flag
= true;
for (int k = 0; (k < P)&& flag; k++)
{
if (In[i][P + 1 + k] + In[j][1+k] == 1)
flag
= false;
}
if (flag)
c[i][j]
= min(In[i][0], In[j][0]);
}
}
}
memcpy(G, c,
sizeof(c));
flow
= maxflow(S, E);
M
= 0;

for (int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
if (c[i][j] < G[i][j])
{
Out[M][
0] = i + 1;
Out[M][
1] = j + 1;
Out[M][
2] = G[i][j] - c[i][j];
M
++;
}
}
printf(
"%d %d\n", flow, M);
for (int i = 0; i < M; i++)
printf(
"%d %d %d\n", Out[i][0], Out[i][1], Out[i][2]);
}
return 0;
}

 

posted on 2010-11-18 22:23  ltang  阅读(213)  评论(0编辑  收藏  举报

导航