题意
第一行输入数字N为机器个数,P为零件的种类数。
接下来的N行中,第一个数字为此工厂生产产品个数。
前P个数字中是需要的种类,0表示不需要,1表示必须要,2表示可要可不要。
后P个数字是产品的零件种类,0表示有,1表示没有。
建图:
建立一个超级源一个超级汇。
把一个机器分成两个节点i和i+N,流量限制为该机器的总产量。
如果p的产品可以作为q的生产原料则把p+n到q连一条流量限制无限大的边。
匹配的条件是p的产品不是2的地方和q的生产原料1和0的情况相同。
超级源和原料建立边的条件是原料中没有1存在。
产品和超级汇建立边的条件是产品中所有的数字都是1。
这道题的目的就是求这个图的最大流量。用ISAP算法实现(同一个系列中有文章介绍)
输出的生产线的条件是产品到加工品的边的流量不为0。
#include<iostream>
using namespace std;
struct Node
{
int cap, flow;
};
int p, n, size;
int dp1[50][100], dp2[50][100];
Node edges[1000][1000];
int visit[200], s, t;
int p1[1000000], num[1000000];
int q[1000000], d[1000000];
int Count;
int BFS()
{
int i, front, tail,temp;
for(i = 1; i <= size; i++)
{
visit[i] = 0;
}
front = 0; tail = 1;
q[front] = t;
visit[t] = 1;
d[t] = 0;
num[d[t]]++;
while(front < tail)
{
temp = q[front];
front++;
for(i = 1; i <= size; i++)
{
if(!visit[i] && edges[i][temp].cap > edges[i][temp].flow)
{
q[tail] = i;
d[i] = d[temp] + 1;
num[d[i]]++;
visit[i] = 1;
tail++;
}
}
}
return visit[t];
}
int augment()
{
int a = 1000000, temp;
for(int i = 0; i < Count - 1; i++)
{
temp = edges[p1[i]][p1[i + 1]].cap - edges[p1[i]][p1[i + 1]].flow;
if(temp < a)
a = temp;
}
for(int i = 0; i < Count - 1; i++)
{
edges[p1[i]][p1[i + 1]].flow += a;
edges[p1[i + 1]][p1[i]].flow -= a;
}
// for(int i = 0; i < Count ; i++)
// {
// cout << "aaa " << p[i] << " " << a <<endl;
// }
// cout <<endl;
return a;
}
int maxFlow()
{
BFS();
int x = s,i, flow = 0, ok, min, m;
Count = 0; p1[Count++] = s;
while(d[s] < size)
{
if(x == t)
{
flow += augment();
x = s; Count = 0;
p1[Count++] =s;
}
ok = 0;
for(i = 1; i <= size ; i++)
{
if(d[x] == d[i] + 1 && edges[x][i].cap > edges[x][i].flow)
{
ok = 1;
x = i; p1[Count++] = i;
}
}
if(ok == 0)
{
min = size - 1;
for(i = 1; i <= size ; i++)
{
if(edges[x][i].cap > edges[x][i].flow)
{
if(d[i] < min)
{
min = d[i];
m = i;
}
}
}
if(--num[d[x]] == 0)
break;
d[x] = min + 1; num[d[x]]++;
//p[Count++] = m;
//x = m;
if(x != s)
{
x = p1[Count - 2];
Count --;
}
}
}
return flow;
}
void build()
{
int i, j, k;
bool flag;
s = 2 * n + 1; t = 2 * n + 2;
for(i = 1; i <= n; i++)
{
flag = true;
for(j = 1; j <= p; j++)
{
if(dp1[i][j] == 1)
{
flag = false;
break;
}
}
if(flag)
{
edges[2 * n + 1][i].cap = 100000000;
}
}
for(i = 1; i <= n; i++)
{
flag = true;
for(j = 1; j <= p; j++)
{
if(dp2[i][j] == 0)
{
flag = false;
break;
}
}
if(flag)
{
edges[i + n][2 * n + 2].cap = 100000000;
}
}
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
flag = true;
if(i != j)
{
for(k = 1; k <= p; k++)
{
if(dp1[i][k] == dp2[j][k] || dp1[i][k] == 2)
continue;
else
{
flag = false;
break;
}
}
if(flag)
{
edges[j + n][i].cap = 100000000;
}
}
}
}
}
int main()
{
int i, j, temp, num;
while(scanf("%d", &p) != EOF)
{
scanf("%d", &n);
size = 2 * n + 2;
for(i = 1; i <= size; i++)
{
for(j = 1; j <= size; j++)
{
edges[i][j].cap = 0; edges[i][j].flow = 0;
}
}
for(i = 1; i <= n; i++)
{
scanf("%d", &temp);
edges[i][i + n].cap = temp;
for(j = 1; j <= p; j++)
scanf("%d", &dp1[i][j]);
for(j = 1; j <= p; j++)
scanf("%d", &dp2[i][j]);
}
build();
cout << maxFlow();
num = 0;
for(i = n + 1; i <= 2 * n; i++)
{
for(j = 1; j <= n; j++)
{
if(edges[i][j].flow > 0)
{
num ++; }
}
}
cout << " " << num << endl;
for(i = n + 1; i <= 2 * n; i++)
{
for(j = 1; j <= n; j++)
{
if(edges[i][j].flow > 0)
cout << (i - n) << " " << j << " " << edges[i][j].flow << endl;
}
}
}
}