黑白染色,源指向白,黑指向汇,容量都是方格中数的大小,相邻的格子白指向黑,容量为oo,然后求一次最小割。
这个割是一个简单割,如果只选择不在割中的点,那么一种割就和一个选数方案一一对应,割的大小就是不选的那些数的大小,我们需要最小化这个值。
答案=总和-最小割
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <vector> 5 #define maxn 410 6 #define oo 0x3f3f3f3f 7 using namespace std; 8 9 struct Edge { 10 int u, v, f; 11 Edge( int u, int v, int f ):u(u),v(v),f(f){} 12 }; 13 struct Dinic { 14 int n, src, dst; 15 vector<Edge> edge; 16 vector<int> g[maxn]; 17 int dep[maxn], cur[maxn]; 18 19 void init( int n, int src, int dst ) { 20 this->n = n; 21 this->src = src; 22 this->dst = dst; 23 for( int u=1; u<=n; u++ ) 24 g[u].clear(); 25 edge.clear(); 26 } 27 void add_edge( int u, int v, int f ) { 28 g[u].push_back( edge.size() ); 29 edge.push_back( Edge(u,v,f) ); 30 g[v].push_back( edge.size() ); 31 edge.push_back( Edge(v,u,0) ); 32 } 33 bool bfs() { 34 queue<int> qu; 35 memset( dep, 0, sizeof(dep) ); 36 qu.push( src ); 37 dep[src] = 1; 38 while( !qu.empty() ) { 39 int u=qu.front(); 40 qu.pop(); 41 for( int t=0; t<g[u].size(); t++ ) { 42 Edge &e = edge[g[u][t]]; 43 if( e.f && !dep[e.v] ) { 44 dep[e.v] = dep[e.u]+1; 45 qu.push( e.v ); 46 } 47 } 48 } 49 return dep[dst]; 50 } 51 int dfs( int u, int a ) { 52 if( u==dst || a==0 ) return a; 53 int remain=a, past=0, na; 54 for( int &t=cur[u]; t<g[u].size(); t++ ) { 55 Edge &e = edge[g[u][t]]; 56 Edge &ve = edge[g[u][t]^1]; 57 if( dep[e.v]==dep[e.u]+1 && e.f && (na=dfs(e.v,min(remain,e.f))) ) { 58 remain -= na; 59 past += na; 60 e.f -= na; 61 ve.f += na; 62 if( !remain ) break; 63 } 64 } 65 return past; 66 } 67 int maxflow() { 68 int flow = 0; 69 while( bfs() ) { 70 memset( cur, 0, sizeof(cur) ); 71 flow += dfs(src,oo); 72 } 73 return flow; 74 } 75 }; 76 77 int n, m; 78 int idx[23][23], id_clock; 79 int arr[23][23], sum; 80 int di[4] = { 0, 0, +1, -1 }; 81 int dj[4] = { +1, -1, 0, 0 }; 82 Dinic D; 83 84 int main() { 85 while( scanf( "%d", &n )==1 ) { 86 id_clock = 0; 87 sum = 0; 88 for( int i=1; i<=n; i++ ) 89 for( int j=1; j<=n; j++ ) { 90 scanf( "%d", &arr[i][j] ); 91 sum += arr[i][j]; 92 idx[i][j] = ++id_clock; 93 } 94 D.init( id_clock+2, id_clock+1, id_clock+2 ); 95 for( int i=1; i<=n; i++ ) 96 for( int j=1; j<=n; j++ ) { 97 if( (i+j)&1 ) { 98 D.add_edge( D.src, idx[i][j], arr[i][j] ); 99 for( int d=0; d<4; d++ ) { 100 int ni = i+di[d]; 101 int nj = j+dj[d]; 102 if( 1<=ni&&ni<=n && 1<=nj&&nj<=n ) { 103 int u = idx[i][j]; 104 int v = idx[ni][nj]; 105 D.add_edge( u, v, oo ); 106 } 107 } 108 } else { 109 D.add_edge( idx[i][j], D.dst, arr[i][j] ); 110 } 111 } 112 printf( "%d ", sum-D.maxflow() ); 113 } 114 }