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