首页 > 技术文章 > poj3436(ACM Computer Factory)

ZhaoPengkinghold 2014-07-20 09:24 原文

题目地址:ACM Computer Factory

 

题目大意:

    一个生产电脑的工厂,有多个机器生产一台电脑,大家都知道一台电脑有多个零部件,这些机器在一个流水线,有些机器工作的前提是需要一些零部件的存在才能继续工作生产,每个机器都有输入设备和输出设备,输入设备意思是根据这几个零部件的存在状态才能使此机器工作,状态包含(0,该零部件不需要存在,1,该零部件必须存在,2,该零部件可有可无)。输出设备意思为该机器工作之后生产的电脑的零部件状态情况(0,没有生产1,生成出该零件)。p,代表每个电脑零部件的个数,m代表几个机器,还给出了每个机器最大的限度能够同时处理机器的个数。根据输入算出最多可以生产的电脑数量和路径个数和路径的详情。

 

解题思路:

    难点在于建图,首先定义一个tu[n][n]数组,组里第一个单位存的是机器最大限度的生产电脑个数,后面的单位存机器的输入和输出。源点是tu[0][n],全定义为0,汇点是tu[n+1][n],全定义为1.然后根据输入设备和输出设备将各个机器连通并赋值容量。注意:输出的路径不包含重复的路径,加入第一次走1->3 (2),下次又走了一次1->3(1).这时候应该输出1->3(3)。我这里的输出是用out数组输出的,刚开始只有这一句out[last][k]+=increasement; 但是忘了路径可能反方向走这时候路径的流量就会改变,应该加上out[k][last]-=increasement; 这题还有一个小毛病就是假如有2指向3的路径容量为1,没有3指向2的路径,第一次走2->3(1)这时map[2][3]=0,map[3][2]=1。out[2][3]=1 out[3][2]=-1,下次走了3->2(1)时out[3][2]=0 out[2][3]=0.这两个路径都不输出??

 

代码:

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cstdio>
  7 #include <string>
  8 #include <bitset>
  9 #include <vector>
 10 #include <queue>
 11 #include <stack>
 12 #include <cmath>
 13 #include <list>
 14 //#include <map>
 15 #include <set>
 16 using namespace std;
 17 /***************************************/
 18 #define ll long long
 19 #define int64 __int64
 20 /***************************************/
 21 const int INF = 0x7f7f7f7f;
 22 const double eps = 1e-8;
 23 const double PIE=acos(-1.0);
 24 const int d1x[]= {-1,1,0,0};
 25 const int d1y[]= {0,0,-1,1};
 26 const int d2x[]= {0,-1,0,1};
 27 const int d2y[]= {1,0,-1,0};
 28 const int fx[]= {-1,-1,-1,0,0,1,1,1};
 29 const int fy[]= {-1,0,1,-1,1,-1,0,1};
 30 /***************************************/
 31 void openfile()
 32 {
 33     freopen("data.in","rb",stdin);
 34     freopen("data.out","wb",stdout);
 35 }
 36 /**********************华丽丽的分割线,以上为模板部分*****************/
 37 #define arraysize 201
 38 int maxData = 0x7fffffff;
 39 int map[arraysize][arraysize]; //记录残留网络的容量
 40 int flow[arraysize];                //标记从源点到当前节点实际还剩多少流量可用
 41 int pre[arraysize];                 //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
 42 int p,n;
 43 int tu[arraysize][arraysize];
 44 int out[arraysize][arraysize];
 45 int map1[arraysize][arraysize];
 46 queue<int> myqueue;
 47 int BFS(int src,int des)
 48 {
 49     int i,j;
 50     while(!myqueue.empty())       //队列清空
 51         myqueue.pop();
 52     for(i=0; i<=n; ++i)
 53     {
 54         pre[i]=-1;
 55     }
 56     pre[src]=0;
 57     flow[src]= maxData;
 58     myqueue.push(src);
 59     while(!myqueue.empty())
 60     {
 61         int index = myqueue.front();
 62         myqueue.pop();
 63         if(index==des)            //找到了增广路径
 64             break;
 65         for(i=0; i<=n; ++i)
 66         {
 67             if(i!=src && map[index][i]>0&&pre[i]==-1)
 68             {
 69                 pre[i] = index; //记录前驱
 70                 flow[i] = min(map[index][i],flow[index]);   //关键:迭代的找到增量
 71                 myqueue.push(i);
 72             }
 73         }
 74     }
 75     if(pre[des]==-1)      //残留图中不再存在增广路径
 76         return -1;
 77     else
 78         return flow[des];
 79 }
 80 int maxFlow1(int src,int des)
 81 {
 82     int increasement=0;
 83     int sumflow=0;
 84     int cnt=0;
 85     memset(out,0,sizeof(out));
 86     while((increasement=BFS(src,des))!=-1)
 87     {
 88         int k = des;          //利用前驱寻找路径
 89         while(k!=src)
 90         {
 91             int last = pre[k];
 92             map[last][k]-=increasement; //改变正向边的容量
 93             map[k][last]+=increasement; //改变反向边的容量
 94             out[last][k]+=increasement;
 95             out[k][last]-=increasement;
 96             k=last;
 97 
 98         }
 99         sumflow+=increasement;
100     }
101     printf("%d ",sumflow);
102     for(int i=1; i<n; i++)
103         for(int j=1; j<n; j++)
104             if (out[i][j]>0)
105                 cnt++;
106     printf("%d\n",cnt);
107     for(int i=1; i<n; i++)
108         for(int j=1; j<n; j++)
109             if (out[i][j]>0)
110                 printf("%d %d %d\n",i,j,out[i][j]);
111     return 0;
112 }
113 int main()
114 {
115     while(scanf("%d%d",&p,&n)!=EOF)
116     {
117         memset(map,0,sizeof(map));
118         memset(flow,0,sizeof(flow));
119         memset(tu,0,sizeof(tu));
120         int i,j,k;
121         for(i=1; i<2*p+1; i++)
122         {
123             tu[0][i]=0;
124             tu[n+1][i]=1;
125         }
126         for(i=1; i<=n; i++)
127             for(j=0; j<p*2+1; j++)
128             {
129                 scanf("%d",&tu[i][j]);
130             }
131         n=n+1;
132         for(i=0; i<=n; i++)
133             for(j=0; j<=n; j++)
134             {
135                 if (i==j)
136                     continue;
137                 int cnt=0;
138                 for(k=1; k<=p; k++)
139                 {
140                     if (tu[j][k]==2||tu[i][k+p]==tu[j][k])
141                         cnt++;
142                 }
143                 if (cnt==p&&i==0)
144                     map[i][j]=tu[j][0];
145                 else if (cnt==p&&j==n)
146                     map[i][j]=tu[i][0];
147                 else if (cnt==p)
148                     map[i][j]=min(tu[i][0],tu[j][0]);
149             }
150         maxFlow1(0,n);
151     }
152     return 0;
153 }
View Code

推荐阅读