CF1198E 사각형 그림 2 (생각의 최소 컷

주요 질문은 나쁜 생각의 작은 아이디어로 절단됩니다.

효과 : 당신이 흰색으로 염색해야 검은 색 큰 광장, 블랙 어떤 시점, 어떤 화이트 포인트, 당신은 사각형 스테인드 비용 분을 선택할 수 있습니다 때마다 (길이, 폭), 최소 요구 가격을 제공합니다.

아이디어 : 블록을 염색하기 위해서는 자신이 행 또는 열이 커버로 피복되어야한다 (옵션 소형), 분 (컬럼의 수를 나타내는, 행의 수를 차지)된다. 다음 그래서 네트워크 흐름을 구축 할 수 있습니다 : 소스 -> 라인 노드 (용량이 행의 수를 나타내는) -> 무한 측 -> 열 노드 (용량이 열 수를 나타내는) -> 다음 최소 컷을 실행 싱크 (최대 유량 ).

#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을 반환; 
}

 

추천

출처www.cnblogs.com/wzgg/p/11441106.html