주요 질문은 나쁜 생각의 작은 아이디어로 절단됩니다.
효과 : 당신이 흰색으로 염색해야 검은 색 큰 광장, 블랙 어떤 시점, 어떤 화이트 포인트, 당신은 사각형 스테인드 비용 분을 선택할 수 있습니다 때마다 (길이, 폭), 최소 요구 가격을 제공합니다.
아이디어 : 블록을 염색하기 위해서는 자신이 행 또는 열이 커버로 피복되어야한다 (옵션 소형), 분 (컬럼의 수를 나타내는, 행의 수를 차지)된다. 다음 그래서 네트워크 흐름을 구축 할 수 있습니다 : 소스 -> 라인 노드 (용량이 행의 수를 나타내는) -> 무한 측 -> 열 노드 (용량이 열 수를 나타내는) -> 다음 최소 컷을 실행 싱크 (최대 유량 ).
#INCLUDE <. 비트 / stdc ++ H> #DEFINE M 405 std 네임 스페이스를 사용하여; CONST INT의 INF = 1E9; INT의 N, M, S, T, H [M], TT = 1; 구조체 노드 {INT의 X1, Y1, X2, Y2,} A [M]; 불리언 예 [M] [M]; INT B1 [M *에서의 M, B1, B2 [M *에서의 M, B2; 구조체 {가장자리에 INT의 NXT, CO} G [M *에서의 M]; 보이드 추가 {(a, INT의 B, C의 INT를 INT) 경우 (예를 들어 [A] [B])를 호출; G [++ TT = (에지) {H [A], B, C}; H는 [A]를 TT =; 예를 들어, [A]는 [B] = 1; } INT DEP [M], [M]을 CUR; 큐 <INT> Q; 불리언 BFS () { memset 함수 (DEP, -1는 sizeof (DEP)); 대해 (ⅰ에게 = s의 값 int; I <= t; 내가 ++) CUR [I] = H의 [I]; 반면 Q.pop () (Q.empty ()!); Q.push (S) DEP [S] = 0; 동안 (! Q.empty ()) { X = INT Q.front (); Q.pop (); 대해 INT (I = H [X] I, I = G [I] .nxt) { INT U = G [I] .TO, C = G [I] .co와; 경우 (DEP [U] = 1 - C ||!) 계속; DEP [U] = DEP [X] +1; 만약 (U == t) 창 1; Q.push (U); } } 0을 리턴; } INT DFS (INT (X), INT MI) { 경우 (X == t || MI!) 복귀 MI; INT RLOW = 0, 사용 = 0; 대 (INT 및 I = CUR [X] 나, I = G [I] .nxt) { INT U = G [I] .TO, C = G [I] .co와; 만약 (! DEP [U] = DEP [X] +1 || C!) 계속; (RLOW = DFS (U는 분 (c는, MI가 사용되는))) {경우 사용 + = RLOW; G [I] = .co- RLOW; G [I ^ 1] + = RLOW .co와; (사용 == MI) 어기면; } } 사용 반환; } INT ANS = 0; 보이드 Dinic () { 동안 (BFS ()) = + ANS DFS (S, INF); } INT의 main () { 는 scanf ( "% d 개 %의 D", 및 N, m); 대해 INT (I = 1; I <= m; 내가 ++) { 는 scanf ( "% D % D % D % D ', A [i]를 .x1, A [i]를 .y1, A [i]를 .x2, & A [I] .y2); B1의 [B1 ++] ++ = A [i]를 .x2] B1 [++ B1] A [I]를 .x1 =; B2의 [++ B2 = ++ A [i]를 .y2] B2 [++ B2] A [I]를 .y1 =; } B1의 [++ B1 = B2의 [++ B2] = N + 1; 정렬 (B1 + 1, B1 + B1 + 1), 정렬 방법 (B2 + 1, B2 + B2 + 1); B1 = 고유 (B1 + 1, B1 + B1 + 1) -B1-1; B2 = 고유 (B2 + 1, B2 + B2 + 1) -B2-1; S = 0, t = B1 + B2 + 1; 대해 INT (I = 1; I <= m; 내가 ++) { A [i]를 .x1 LOWER_BOUND = (B1 + 1, B1 + B1 + 1, A [i]를 .x1) -B1; A [i]를 .x2 LOWER_BOUND = (B1 + 1, B1 + B1 + 1, A [i]를 .x2) -B1; A [I] = .y1 LOWER_BOUND (B2 + 1, B2 + B2 + 1, A [i]를 .y1) -B2; A [I] = .y2 LOWER_BOUND (B2 + 1, B2 + B2 + 1, A [i]를 .y2) -B2; 대 INT (X = A [i]를 .x1; X <A [i]를 .x2, X ++) 에 대해 (int로 Y는 = A [i]를 .y1; Y <A [i]를 .y2; ++, Y) (X 추가, Y 용의 + B1, INF) 추가 (Y의 + B1의, X, 0); } 에 대해 (나는은 B1 <; I = 1 int로 난 ++)이 {추가 (S, I, B1의 [I + 1] -B1 [I])에 추가 (I, S, 0)} 에 대한 (INT I = 1 ; 나는 B2 <; 내가 ++) {; 추가 (t, 난 + B1,0) 추가 (ⅰ B1, t, B2의 [내가 + 1] -B2 [I]) +} Dinic ()의 printf ( "%의 D를 \ n ", ANS); 0을 반환; }