質問は、表面:
https://www.luogu.org/problemnew/show/P3355
ソリューション:
水题,染色+最小割。
#include <cstdioを> する#include <CStringの> する#include <iostreamの> する#include <ベクトル> の#include <キュー> の#define RIレジスタint型 の#define N 50000 の#define INF十億七 の#define S 0 の#define T(N * N + 1) 使用して 名前空間STDを、 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 ]。 構造体グラフ{ ベクトル < 整数 > に、W。 ベクター < INT > ED [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] .size(); iはLを<; iは++ ){ int型、E = ED [X] [I]; もし(W [E] && D [X] + 1< D [乃至[E]]){ D [乃至[E] = D [X] + 1 。 ([E]に)q.push。 } } } 戻り D [T] < INF。 } INT DFS(int型のx、int型制限){ 場合(!X == T ||限界)リターンリミット。 int型 TOT = 0 ; 用(RI&I = CUR [X]; iは<ED [X] .size(); iは++ ){ int型、E = ED [X] [I]; もし(D [X] + == D [E]に】1 && {W [E]) INT = FDFS([E]、分(限界に、W [E]))。 もし(!f)を続けます。 W [E] - = F。[W 1 ^ E] + = F。 TOT + = F。リミット-側= F。 もし(!リミット)リターンTOT; } } 戻りTOT。 } int型dinic(){ int型 RET = 0 。 一方、(BFS()){ memsetの(CUR、0、はsizeof (CUR))。 RET + = DFS(S、INF)。 } 戻りRET。 } } G。 INT {main()の のscanf(" %d個の%のD "、&N、&M)。 用(RI i = 1 ; I <= M; iは++ ){ 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]){ 合計 ++ 。 場合(式(I + J)%2 == 0 ){ G.add_edge(S、N *(I-1)+ J、1 )。 用(RI k = 0 ; K < 8 ; kは++ ){ int型 NX = iがDX [K]、NY = J + 1 + DY [k]を、 もし(NX> = 1 && NX <= N && NY> = 1 && NY <= N && G [NX] [NY] == 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。 }