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 }

转载于:https://www.cnblogs.com/ac2012/archive/2011/03/16/1986421.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值