Zoj_3613
This topic requires that a resource be supplied to only one factory. In fact, the number of factories in each connected block must be greater than or equal to the number of resources. Otherwise, some resources will be useless, it will increase unnecessary costs. In this way, if this implicit condition is added to the final DP, the number of resources in the connected block can be counted instead of the number of factories that can work.
We also recommend a blog with a better understanding of such issues: http://endlesscount.blog.163.com/blog/static/8211978720125113427573 /.
# Include <stdio. h> # Include < String . H> # Define Maxd 210 # Define Maxm 10010 # Define St 266 # Define # Maxq 2000010 # Define INF 0x3f3f3f Const Int Q = 2000000 ; Int N, m, NN, FN, Sn, first [maxd], E, next [maxm], V [maxm], W [maxm]; Int Bit [maxd], Q [maxq], INQ [maxd] [st], front, rear; Int F [maxd] [st], DP [st]; Int Sum [ 10 ]; Struct Planet { Int A, B;} p [maxd]; Void Add ( Int X, Int Y, Int Z) {v [E] = Y, W [e] = Z; next [E] = First [X], first [x] = e ++ ;} Void Init (){ Int I, J, K, x, y, z; FN = Sn = 0 ; For (I = 1 ; I <= N; I ++ ) Scanf ( " % D " , & P [I]. A, & P [I]. B), FN + = P [I]. A> 0 , Sn + = P [I]. B; NN = 1 <FN + Sn; memset (bit, 0 , Sizeof (BIT )); For (I = 1 , K = 0 ; I <= N; I ++) If (P [I]. A) sum [k] = P [I]. A, bit [I] | = 1 <(K ++ ); For (I = 1 ; I <= N; I ++) If (P [I]. B) bit [I] | = 1 <(K ++); Memset (F, 0x3f , Sizeof (F )); For (I = 1 ; I <= N; I ++) If (Bit [I]) f [I] [bit [I] = 0 ; Memset (first, - 1 , Sizeof (First); e = 0 ; Scanf ( " % D " ,& M ); For (I = 0 ; I <m; I ++ ) {Scanf ( " % D " , & X, & Y ,& Z); add (x, y, z), add (Y, x, z) ;}} inline Int Min ( Int X, Int Y ){ Return X <Y? X: Y ;} Void Spfa (){ Int I, X, St, Y, NST; While (Front! = Rear) {x = Q [Front] & 255 , St = Q [Front]> 8 , INQ [x] [st] = 0 ; ++ Front> q? Front =0 : 0 ; For (I = first [X]; I! =- 1 ; I = Next [I]) {Y = V [I], NST = sT | Bit [y]; If (F [x] [st] + W [I] < F [y] [NST]) {f [y] [NST] = F [x] [st] + W [I]; If (NST = sT &&!INQ [y] [NST]) {q [rear ++] = NST < 8 | Y, INQ [y] [NST] = 1 ; Rear > Q? Rear = 0 : 0 ;}}}}} Bool Check ( Int St ){ Int I, n = 0 ; For (I = 0 ; I <FN; I ++) If (St & 1 <I) N + = Sum [I]; For (; I <FN + Sn; I ++) If (St & 1 <I )-- N; Return N> = 0 ;} Void Update (Int St, Int C, Int & Num, Int & Cost ){ Int I, n = 0 ; For (I = 0 ; I <Sn; I ++) If (St & 1 <I + FN) ++ N; If (N> num | (n = num & C < Cost) num = N, cost = C ;} Void Solve (){ Int I, J, K, num, cost; front = Rear = 0 ; For (I = 0 ; I <nn; I ++ ){ For (J = 1 ; J <= N; j ++){ For (K = I- 1 & I; k = k- 1 & I) f [J] [I] = Min (F [J] [I], F [J] [k | bit [J] + F [J] [I-k | Bit [J]); If (F [J] [I] < INF) Q [rear ++] = I < 8 | J, INQ [J] [I] = 1 ; Rear > Q? Rear =0 : 0 ;} Spfa ();} For (I = 0 ; I <nn; I ++ ) {DP [I] = INF; For (J = 1 ; J <= N; j ++ ) DP [I] = Min (DP [I], F [J] [I]);} num = 0 , Cost = 0 ; For (I = 0 ; I <nn; I ++ ) If (Check (I )){ For (J = I- 1 & I; j = J- 1 & I) If (Check (j) & check (I- J) DP [I] = Min (DP [I], DP [J] + dp [I-J]); If (DP [I] < INF) Update (I, DP [I], num, cost);} printf ( " % D \ n " , Num, cost );} Int Main (){ While (Scanf ( " % D " , & N) = 1 ) {Init (); solve ();} Return 0 ;}