POJ3436

来源:互联网 发布:知乎 北上广深 编辑:程序博客网 时间:2024/05/22 08:01

题意

第一行输入数字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;}}}}  


0 0