네트워크 흐름 문제 [24] 나이트 공존 문제

질문 표면 :

https://www.luogu.org/problemnew/show/P3355

해결 방법 :

水题 염색 + 최소 비율.

#INCLUDE <cstdio> 
#INCLUDE <CString을> 
#INCLUDE <iostream> 
#INCLUDE <벡터> 
#INCLUDE <큐>
 #DEFINE RI 레지스터의 INT
 #DEFINE N 50000
 #DEFINE의 INF 1,000,000,007
 #DEFINE의 S 0
 #DEFINE T (n 개 * n 개의 + 1)
 사용  스페이스 성병; 

CONST의  INT DX [] = {- 2 - 2 - 1 - 1 , 1 , 1 , 2 , 2 }, DY [] = { 1 - 1 , 2 -2 - 2 , 2 , 1 , - 1 };
INT의 N, M, X, Y, g [ 250 ] [ 250 ]; 

구조체 그래프 { 
  벡터 < INT > w로; 
  벡터 < INT > 혼성 [N];
  INT의 CUR [N], D [N];
  보이드 의 add_edge ( int로 U, INT의 V, INT의 {W1)
     // COUT << << U ","V << << ''<< W1 << ENDL; 
    to.push_back (V); w.push_back (W1); ED [U] .push_back (to.size () - 1  );
    to.push_back (U)] w 0 ); ED [V] .push_back (to.size () - 1 ); 
  } 
  BOOL BFS () {  < INT > Q; 
    memset 함수 (d, 0x3F입니다 , 는 sizeof (d)); 
    D는 [ 0 ] = 0 ; q.push ( 0 );
    반면 (! {q.empty ())
       INT (X) = q.front (); q.pop ();
       (RI I = 0 , L = ED [X] 크기는 (); 나는 <L을, 난 ++ ) {
         INT의 E = ED [X] [I];
        만약 (w [E] && D [X] + 1 < D [내지 [E]) { 
          D [내지 [E] = D [X] + 1 ; 
          q.push (내지 [E]); 
        } 
      } 
    } 
    리턴 D [T] < INF; 
  } 
  INT DFS ( INT (X), INT의 제한) {
     경우 (X == T || 제한!의) 복귀 한도
    INT의 TOT = 0 ;
     (RI 및 I = CUR [X] 난 <ED [X] 크기는 (); 나는 ++ ) {
       INT의 E = ED [X] [I];
      경우 (d [내지 [E] == D [X] + 1 && w [E]) {
         INT의 F =DFS ([E], 분 (한계, w [E]));
        경우 (F!) 계속 ; 
        w [E] - = F; [w 1 ^ E] + = F; 
        TOT + = F; LIMIT- = F;
        만약 (! 제한) 반환 TOT; 
      } 
    } 
    반환 TOT; 
  } 
  INT의 dinic () {
     INT RET = 0 ;
    반면 (BFS ()) { 
      memset 함수 (현재, 0 , 는 sizeof (현재)); 
      RET + = DFS (S, INF); 
    } 
    반환 RET를; 
  } 
} G; 

값 int () {메인
  scanf와 ( " %의 D % d에 " , N, m);
   (RI I = 1 ; I <= m; 내가 ++ ) { 
    는 scanf ( " % d 개 %의 D ' , X, Y); 
    g [X] [Y]는 = 1 ; 
  } 
  INT의 합 = 0 ;
   (RI I = 1 ; I <= N; I ++ ) 
      RI (J = 1 , J <= N; J ++) 경우 (!의 g [I] [J]) {  ++ ;
      경우 ((나는 J) % + 2 == 0  ) {
        G.add_edge (S를, N * (I-1 ) + J, 1 );
         (RI K = 0 ; K < 8 ; 케이 ++ ) {
           INT의 NX = 난 DX [K], NY = J +에 +를 DY [K]을;
          경우 (NX> = 1 && NX <= N && NY> = 1 && NY <= N && g [NX] [뉴욕] == 0 ) G.add_edge (N *을 (I- 1 ) + J, N * ( NX- 1 ) + NY, INF); 
        } 
      } 
       G.add_edge (N *을 (I- 1 ) + J, T, 1 ); 
    } 
  COUT << 합 G.dinic () << ENDL; 
}

추천

출처www.cnblogs.com/shxnb666/p/11183090.html