Obviously, a bipartite graph is matched multiple times, and the network stream is used to create a graph at the beginning. It's a tragic TLE.
After that, I read the online explanation and scaled down the point, which greatly simplifies the problem. The problem can also be AC, 600 + MS.
In the first place, a figure is created in this way. First, the virtual Source Vertex s and the sink vertex t are connected to each person by a side with a capacity of 1, each person connects one side to each appropriate planet with a capacity of one side, and then connects one side from each planet with a capacity of W [I] (capacity of the planet). Obviously, determine whether the maximum stream is equal to n. N is 100000, while M is only 10.
In fact, there is no difference between people in this question. The difference is that they have their own choices, and there are only 10 planet in total, that is, the number of all choices is (1 <10). It is equivalent for all people with the same choices !!!
However, I did not expect to optimize I/O, and it suddenly went to 100 + Ms. orz
Or Hungary.AlgorithmAfter I/O optimization, 171 MS is not slow, andCodeVery simple
Hungary Algorithm
# Include <iostream> # Include < String > Using Namespace STD; Const Int N = 100002 ; Int Cap [ 12 ], Map [N] [ 12 ], Vlink [ 12 ], Link [ 12 ] [N]; Bool Vis [ 12 ]; Int N, m; Int In (){ Char Ch; Int A = 0 ; While (CH = getchar () = ' ' | CH = ' \ N ' ); + = CH- ' 0 ' ; While (CH = getchar ())! = ' ' & Ch! = ' \ N ' ) { * = 10 ; + = CH- ' 0 ' ;} Return A ;} Int PATH ( Int S ){ For ( Int I = 0 ; I <m; I ++ ){ If (Map [s] [I] &! Vis [I]) {vis [I] = True ; If (Vlink [I] <Cap [I]) {link [I] [vlink [I] ++] = S; Return 1 ;} For ( Int J = 0 ; J <vlink [I]; j ++ ){ If (Path (link [I] [J]) {link [I] [J] = S; Return 1 ;}}}} Return 0 ;} Int Main (){ While (Scanf ( " % D " , & N, & M) = 2 ){ For ( Int I =0 ; I <n; I ++ ) For ( Int J = 0 ; J <m; j ++ ) Map [I] [J] = In (); For ( Int I = 0 ; I <m; I ++ ) Scanf ( " % D " ,& Cap [I]); memset (vlink, 0 , Sizeof (Vlink )); Bool Flag = True ; For ( Int I = 0 ; I <n; I ++ ) {Memset (VIS, False , Sizeof (VIS )); If (! PATH (I) {flag = False ; Break ;}} If (FLAG) puts ( " Yes " ); Else Puts ( " No " );} Return 0 ;}
Max stream + shrinkage point
# Include <iostream> # Include <Algorithm> # Include < String > Using Namespace STD; Const Int N =120000 + 20 ; Int N; Int Size, head [N], DIS [N], gap [N], pre [N], cur [N]; Int Mm [( 1 < 12 )]; Struct Edge { Int V, W, next; edge () {} edge ( Int V, Int Next, Int W = 0 ): V (V), next (next), w (w) {}} E [n * 30 ]; Inline Void Insert ( Int U, Int V, Int W) {e [size] = Edge (v, head [u], W); head [u] = Size ++ ; E [size] = Edge (u, head [v],0 ); Head [v] = Size ++ ;} Int ISAP ( Int SRC, Int Des ){ Int Maxflow = 0 ; Memset (DIS, 0 , Sizeof (DIS); memset (gap, 0 , Sizeof (GAP )); For ( Int I = 0 ; I <= N; I ++ ) Cur [I] = Head [I]; Int U = pre [SRC] = SRC; Int Aug =- 1 ; While (DIS [SRC] < N) {loop: For (Int & I = cur [u]; I! =- 1 ; I = E [I]. Next ){ Int V = E [I]. V; If (E [I]. W & dis [u] = dis [v] + 1 ) {Aug = Min (Aug, E [I]. W); Pre [v] = U; u = V; If (V =Des) {maxflow + = Aug; For (U = pre [u]; V! = SRC; V = u, u = Pre [u]) {e [cur [u]. W -= Aug; E [cur [u] ^ 1 ]. W + = Aug;} Aug = Int_max ;} Goto Loop ;}} Int MDIs =N; For ( Int I = head [u]; I! =- 1 ; I = E [I]. Next ){ Int V = E [I]. V; If (E [I]. W & MDIs> Dis [v]) {cur [u] = I; MDIs = Dis [v] ;}} If (-- Gap [dis [u]) =0 ) Break ; Gap [dis [u] = MDIs + 1 ] ++ ; U = Pre [u];} Return Maxflow ;} Int In (){ Char Ch; Int A =0 ; While (CH = getchar () = ' ' | CH = ' \ N ' ); + = CH- ' 0 ' ; While (CH = getchar ())! = ' ' & Ch! = ' \ N ' ) { * = 10 ; + = CH- ' 0 ' ;} Return A ;} Int Main (){ Int M, A, B; While (Scanf ( " % D " , & N, & M) = 2 ) {Size = 0 ; Memset (Head, - 1 , Sizeof (Head); memset (mm, 0 , Sizeof (Mm )); For ( Int I = 0 ; I <n; I ++ ){ Int T = 0 ; For ( Int J = 0 ; J <m; j ++ ) { = In (); If (A) T | = ( 1 < J);} Mm [T] ++ ;} Int Nn = ( 1 <M), S = 1 , T = nn + M + 2 ; Int N1 = N; n = T; For ( Int I = 1 ; I <nn; I ++){ If (Mm [I] = 0 ) Continue ; Insert (S, I + 2 , Mm [I]); For ( Int J = 0 ; J <m; j ++ ){ If (I &( 1 <J) insert (I + 2 , J + nn + 2 , Mm [I]) ;}} For ( Int I = 0 ; I <m; I ++ ) {Scanf ( " % D " ,& B); insert (I + Nn + 2 , T, B );} If (ISAP (S, T)> = N1) puts ( " Yes " ); Else Puts ( " No " );} Return 0 ;}