【最大流】POJ3236-ACM Computer Factory

【题意】

装配一个电脑需要P个零件,现在给出N机器的信息,每个机器可以将k个电脑由状态{S1,S2..,Sp}转变为{Q1,Q2..,Qp},问最多能装配多少台电脑以及对应的方案?

【思路】

1A..拆点,将每个机器状态S到状态Q的容量设为k,其余的设为INF。设置{0,0,0}(或含有2)和源点连接,{1,1,1}(或含有2)和汇点连接。用Dinic跑一次最大流,反向边最后的容量就是方案。

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<cstdlib>
  7 #include<vector>
  8 #include<cmath>
  9 #include<queue>
 10 using namespace std;
 11 struct node 
 12 {
 13     int to,pos,cap;
 14 };
 15 const int MAXN=55;
 16 const int MAXP=15;
 17 const int MAXM=130;
 18 const int INF=0x7fffffff;
 19 int n,p;
 20 int s[MAXN][MAXP],q[MAXN][MAXP],value[MAXN];
 21 int vis[MAXM];
 22 vector<node> E[MAXM*MAXM];
 23 int dis[MAXM];
 24 int flow;
 25 
 26 void addedge(int u,int v,int w) 
 27 {
 28     /*
 29     POJ必须写成如下形式才能A,否则会CE 
 30     node tmp;
 31     tmp.to=v;
 32     tmp.pos=E[v].size();
 33     tmp.cap=w;
 34     E[u].push_back(tmp);
 35     tmp.to=u;
 36     tmp.pos=E[u].size()-1;
 37     tmp.cap=0;
 38     E[v].push_back(tmp);
 39     */
 40     E[u].push_back((node){v,E[v].size(),w});
 41     E[v].push_back((node){u,E[u].size()-1,0});
 42 }
 43 
 44 void init() 
 45 {
 46     scanf("%d%d",&p,&n) ;
 47     for (int i=0; i<n; i++) 
 48     {
 49         scanf("%d",&value[i]);
 50         for (int j=0; j<p; j++) 
 51             scanf("%d",&s[i][j]);
 52         for (int j=0; j<p; j++) 
 53             scanf("%d",&q[i][j]);
 54     }
 55 }
 56 
 57 void buildup() 
 58 {
 59     /*拆点*/
 60     for (int i=0; i<n; i++)
 61         addedge(i*2+1,i*2+2,value[i]);
 62 
 63     /*如果流入全为0或2,则与源点相连*/
 64     for (int i=0; i<n; i++) 
 65     {
 66         int flag=1;
 67         for (int j=0; j<p; j++) if (s[i][j]==1) 
 68         {
 69                 flag=0;
 70                 break;
 71         }
 72         if (flag) addedge(0,i*2+1,INF);
 73     }
 74 
 75     /*如果流出全为1或2,则与汇点相连*/
 76     for (int i=0; i<n; i++) 
 77     {
 78         int flag=1;
 79         for (int j=0; j<p; j++) if (q[i][j]==0)
 80         {
 81                 flag=0;
 82                 break;
 83         }
 84         if (flag) addedge(i*2+2,n*2+1,INF);
 85     }
 86 
 87     /*连边*/
 88     for (int i=0; i<n; i++)
 89         for (int j=0; j<n; j++) 
 90         {
 91             int flag=1;
 92             for (int k=0; k<p; k++)
 93                 if ((q[i][k]==1 && s[j][k]==0) || (q[i][k]==0 && s[j][k]==1)) 
 94                 {
 95                     flag=0;
 96                     break;
 97                 }
 98             if (flag) addedge(i*2+2,j*2+1,INF);
 99         }
100 }
101 
102 int bfs() 
103 {
104     memset(dis,-1,sizeof(dis));
105     queue<int> que;
106     que.push(0);
107     dis[0]=0;
108 
109     while (!que.empty()) 
110     {
111         int head=que.front();
112         que.pop();
113         for (int i=0; i<E[head].size(); i++) 
114         {
115             node tmp=E[head][i];
116             if (dis[tmp.to]!=-1 || tmp.cap<=0) continue;
117             dis[tmp.to]=dis[head]+1;
118             que.push(tmp.to);
119         }
120     }
121     if (dis[2*n+1]==-1) return 0;
122     else return 1;
123 }
124 int dfs(int s,int t,int f)
125 {
126     int ret=0;
127     if (s==t) return f;
128     vis[s]=1;//不要忘记这里要设置为访问过 
129     for (int i=0;i<E[s].size();i++)
130     {
131         node &tmp=E[s][i]; 
132         if (vis[tmp.to]==0 && tmp.cap>0)
133         {
134             int delta=dfs(tmp.to,t,min(tmp.cap,f));
135             if (delta>0)
136             {
137                 ret+=delta;
138                tmp.cap-=delta;
139                E[tmp.to][tmp.pos].cap+=delta;
140                f-=delta; 
141             }
142         }
143     }
144     return ret;
145 }
146 
147 void Dinic() 
148 {
149     flow=0;
150     while (bfs()) 
151     {
152         for (;;) 
153         {
154             memset(vis,0,sizeof(vis));
155             int f=dfs(0,2*n+1,INF);
156             if (f==0) break;
157             else flow+=f;
158         }
159     }
160 }
161 
162 void output() 
163 {
164     cout<<flow<<' ';
165     int M=0,l[MAXN],r[MAXN],c[MAXN];
166     for (int i=1; i<2*n+1; i++)
167         for (int j=0; j<E[i].size(); j++) 
168         {
169             node tmp=E[i][j];
170             if (E[tmp.to][tmp.pos].cap>0 && E[tmp.to][tmp.pos].cap<=flow && tmp.to!=2*n+1 && ((tmp.to+1)>>1!=(i+1)>>1)) 
171             {
172                 M++;
173                 l[M]=(i+1)>>1;
174                 r[M]=(tmp.to+1)>>1;
175                 c[M]=E[tmp.to][tmp.pos].cap;
176             }
177         }
178     cout<<M<<endl;
179     for (int i=1; i<=M; i++) cout<<l[i]<<' '<<r[i]<<' '<<c[i]<<endl;
180 }
181 
182 int main()
183 {
184         init();
185         buildup();
186         Dinic();
187         output();
188         return 0;
189 }

 

转载于:https://www.cnblogs.com/iiyiyi/p/5159845.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值