1149

1 /*
2 好题啊,建图可真有意思的一件事
3
4 建图,关键是搞清楚什么事源,什么是汇
5
6 比如此题,源就是猪圈有几头猪,所以source到商人之间的容量时猪圈的里有多少 头猪
7
8 商人到汇点之间的容量是商人要买多少头猪的要求了
9
10 这个必须要搞清楚,因为这个错误N次
11
12 其次,如果有两个商人之间有同一个猪圈的钥匙,那么此商人的流可以直接转到另外几个持有同样钥匙的商人,容量可以无限大。
13
14 这是个非常的经典的网络流题目,非常的好的
15 */
16
17 // include file
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <cmath>
22 #include <cctype>
23 #include <ctime>
24
25 #include <iostream>
26 #include <sstream>
27 #include <fstream>
28 #include <iomanip>
29 #include <bitset>
30
31 #include <algorithm>
32 #include <string>
33 #include <vector>
34 #include <queue>
35 #include <set>
36 #include <list>
37 #include <functional>
38
39 using namespace std;
40
41 // typedef
42 typedef long long LL;
43 typedef unsigned long long ULL;
44 typedef __int64 Bint;
45
46 //
47 #define read freopen("in.txt","r",stdin)
48 #define write freopen("out.txt","w",stdout)
49 #define FORi(a,b,c) for(int i=(a);i<(b);i+=c)
50 #define FORj(a,b,c) for(int j=(a);j<(b);j+=c)
51 #define FORk(a,b,c) for(int k=(a);k<(b);k+=c)
52 #define FORp(a,b,c) for(int p=(a);p<(b);p+=c)
53 #define FORii(a,b,c) for(int ii=(a);ii<(b);ii+=c)
54 #define FORjj(a,b,c) for(int jj=(a);jj<(b);jj+=c)
55 #define FORkk(a,b,c) for(int kk=(a);kk<(b);kk+=c)
56
57 #define FF(i,a) for(int i=0;i<(a);i++)
58 #define FFD(i,a) for(int i=(a)-1;i>=0;i--)
59
60 #define Z(a) (a<<1)
61 #define Y(a) (a>>1)
62
63 const double eps = 1e-6;
64 const double INFf = 1e10;
65 const int INFi = 1000000000;
66 const double Pi = acos(-1.0);
67
68 template<class T> inline T sqr(T a){return a*a;}
69 template<class T> inline T TMAX(T x,T y)
70 {
71 if(x>y) return x;
72 return y;
73 }
74 template<class T> inline T TMIN(T x,T y)
75 {
76 if(x<y) return x;
77 return y;
78 }
79 template<class T> inline void SWAP(T &x,T &y)
80 {
81 T t = x;
82 x = y;
83 y = t;
84 }
85 template<class T> inline T MMAX(T x,T y,T z)
86 {
87 return TMAX(TMAX(x,y),z);
88 }
89
90
91 // code begin
92
93 #define MAXN 110
94
95 class MaxFlow_ISAP
96 {
97 private:
98 int N;
99 int source,sink;
100 int G[MAXN][MAXN];
101
102 int que[MAXN];
103 int dis[MAXN]; //距离
104 int lay[MAXN]; //层个数
105 int pos[MAXN]; //当前弧
106 int fat[MAXN]; //
107
108 public:
109
110 MaxFlow_ISAP(){};
111 MaxFlow_ISAP(int vnum,int so,int sk)
112 {
113 N = vnum;
114 source = so;
115 sink = sk;
116 }
117 void Init()
118 {
119 memset(G,0,sizeof(G));
120 }
121 void Set(int Nt,int sourcet,int sinkt)
122 {
123 N = Nt;
124 source = sourcet;
125 sink = sinkt;
126 }
127 void Add_edge(int a,int b,int c)
128 {
129 G[a][b] = c;
130 }
131 void Print()
132 {
133 FORi(1,N+1,1)
134 {
135 FORj(1,N+1,1)
136 {
137 printf("%d ",G[i][j]);
138 }
139 printf("\n");
140 }
141 printf("\n");
142 }
143 public:
144 void BFS()
145 {
146 int head(0),tail(0);
147 fill(dis,dis+N+1,N);
148 fill(lay,lay+N+1,0);
149 FORi(1,N+1,1)
150 {
151 lay[dis[i]]++;
152 }
153
154 //
155 lay[dis[sink]]--;
156 dis[sink] = 0;
157 lay[dis[sink]]++;
158
159 que[++tail] = sink;
160 while(head!=tail)
161 {
162 int cur = que[++head];
163 FORi(1,N+1,1)
164 {
165 if(G[i][cur]==0 || dis[i]<N) continue;
166 lay[dis[i]]--;
167 dis[i] = dis[cur]+1;
168 lay[dis[i]]++;
169 que[++tail] = i;
170 }
171 }
172 }
173
174 int Augment()
175 {
176 int mind = INFi;
177 int cur = sink;
178 while(cur!=source)
179 {
180 if(G[fat[cur]][cur]<mind)
181 mind = G[fat[cur]][cur];
182 cur = fat[cur];
183 }
184
185 cur = sink;
186 while(cur!=source)
187 {
188 G[fat[cur]][cur] -= mind;
189 G[cur][fat[cur]] += mind;
190 cur = fat[cur];
191 }
192
193 return mind;
194 }
195
196 int Relabel(int &cur)
197 {
198 int tmp,mind(N-1);
199
200 FORi(1,N+1,1)
201 {
202 if(G[cur][i]>0 && dis[i]<mind)
203 mind = dis[i];
204 }
205
206 tmp = dis[cur];
207
208 lay[dis[cur]]--;
209 dis[cur] = 1+mind;
210 lay[dis[cur]]++;
211
212 if(cur!=source)
213 {
214 cur = fat[cur];
215 }
216
217 return lay[tmp];
218 }
219
220 int Maxflow()
221 {
222 int flow(0);
223
224 BFS();
225
226 fill(pos,pos+N+1,1);
227
228 fat[source] = -1;
229 int st = source;
230 while(dis[source]<N)
231 {
232 int ds;
233 for(ds=pos[st];ds<=N;ds++)
234 {
235 if(G[st][ds]>0&&dis[st]==dis[ds]+1)
236 {
237 break;
238 }
239 }
240
241 if(ds<=N)
242 {
243 pos[st] = ds;
244 fat[ds] = st;
245 st = ds;
246 if(st==sink)
247 {
248 flow += Augment();
249 st = source;
250 }
251 }
252 else
253 {
254 pos[st] = 1;
255 if( Relabel(st)==0)
256 break;
257 }
258 }
259 return flow;
260 }
261 };
262
263 int father[1010];
264 int pigs[1010];
265
266 int main()
267 {
268 read;
269 write;
270 int a,b,c,M,N,num,source,sink;
271 MaxFlow_ISAP g;
272 while(scanf("%d %d",&M,&N)!=-1)
273 {
274 g.Init();
275 source = N+1;
276 sink = N+2;
277 g.Set(N+2,source,sink);
278
279 FORi(1,M+1,1)
280 {
281 scanf("%d",pigs+i);
282 father[i] = 0;
283 }
284
285
286 FORi(1,N+1,1)
287 {
288 scanf("%d",&num);
289 c = 0;
290 while(num--)
291 {
292 scanf("%d",&a);
293 // 要连和a相连的
294 if(father[a]==0)
295 {
296 c += pigs[a];
297 father[a] = i;
298 }
299 else
300 {
301 g.Add_edge(father[a],i,INFi);
302 }
303 }
304 scanf("%d",&b);
305 g.Add_edge(source,i,c);
306 g.Add_edge(i,sink,b);
307 }
308 //g.Print();
309 printf("%d\n",g.Maxflow());
310 }
311 return 0;
312 }

posted @ 2011-03-16 21:02  AC2012  阅读(1001)  评论(0编辑  收藏  举报