黑白染色,源指向白,黑指向汇,容量都是方格中数的大小,相邻的格子白指向黑,容量为oo,然后求一次最小割。

这个割是一个简单割,如果只选择不在割中的点,那么一种割就和一个选数方案一一对应,割的大小就是不选的那些数的大小,我们需要最小化这个值。

答案=总和-最小割

 #include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#define maxn 410
#define oo 0x3f3f3f3f
using namespace std; struct Edge {
int u, v, f;
Edge( int u, int v, int f ):u(u),v(v),f(f){}
};
struct Dinic {
int n, src, dst;
vector<Edge> edge;
vector<int> g[maxn];
int dep[maxn], cur[maxn]; void init( int n, int src, int dst ) {
this->n = n;
this->src = src;
this->dst = dst;
for( int u=; u<=n; u++ )
g[u].clear();
edge.clear();
}
void add_edge( int u, int v, int f ) {
g[u].push_back( edge.size() );
edge.push_back( Edge(u,v,f) );
g[v].push_back( edge.size() );
edge.push_back( Edge(v,u,) );
}
bool bfs() {
queue<int> qu;
memset( dep, , sizeof(dep) );
qu.push( src );
dep[src] = ;
while( !qu.empty() ) {
int u=qu.front();
qu.pop();
for( int t=; t<g[u].size(); t++ ) {
Edge &e = edge[g[u][t]];
if( e.f && !dep[e.v] ) {
dep[e.v] = dep[e.u]+;
qu.push( e.v );
}
}
}
return dep[dst];
}
int dfs( int u, int a ) {
if( u==dst || a== ) return a;
int remain=a, past=, na;
for( int &t=cur[u]; t<g[u].size(); t++ ) {
Edge &e = edge[g[u][t]];
Edge &ve = edge[g[u][t]^];
if( dep[e.v]==dep[e.u]+ && e.f && (na=dfs(e.v,min(remain,e.f))) ) {
remain -= na;
past += na;
e.f -= na;
ve.f += na;
if( !remain ) break;
}
}
return past;
}
int maxflow() {
int flow = ;
while( bfs() ) {
memset( cur, , sizeof(cur) );
flow += dfs(src,oo);
}
return flow;
}
}; int n, m;
int idx[][], id_clock;
int arr[][], sum;
int di[] = { , , +, - };
int dj[] = { +, -, , };
Dinic D; int main() {
while( scanf( "%d", &n )== ) {
id_clock = ;
sum = ;
for( int i=; i<=n; i++ )
for( int j=; j<=n; j++ ) {
scanf( "%d", &arr[i][j] );
sum += arr[i][j];
idx[i][j] = ++id_clock;
}
D.init( id_clock+, id_clock+, id_clock+ );
for( int i=; i<=n; i++ )
for( int j=; j<=n; j++ ) {
if( (i+j)& ) {
D.add_edge( D.src, idx[i][j], arr[i][j] );
for( int d=; d<; d++ ) {
int ni = i+di[d];
int nj = j+dj[d];
if( <=ni&&ni<=n && <=nj&&nj<=n ) {
int u = idx[i][j];
int v = idx[ni][nj];
D.add_edge( u, v, oo );
}
}
} else {
D.add_edge( idx[i][j], D.dst, arr[i][j] );
}
}
printf( "%d\n", sum-D.maxflow() );
}
}

最新文章

  1. 非标准JSON解析
  2. WebApi系列~基于单请求封装多请求的设计
  3. 如何利用Direct NFS克隆数据库
  4. gtk+-3.21.4 static build step in windows XP
  5. 无法作为数据库主体执行,因为主体 &quot;dbo&quot; 不存在、无法模拟这种类型的主体,或您没有所需的权限。 已将数据库上下文更改为
  6. Device eth0 does not seem to be present, delaying initialization.转载
  7. ruby中symbol
  8. 新版Windows Azure CDN管理门户正式上线
  9. 致命错误: Python.h:没有那个文件或目录
  10. oracle 11g 报错记录
  11. JQ动画 show hide
  12. 查看Tomcat版本
  13. OBIEE接受外部参数
  14. eclipse使用外部maven时multiModuleProjectDirectory错误解决
  15. 微信公众号开发 VS2015本地调试
  16. Android Studio教程05-Parcelables和Bundles.md
  17. HTML- 标签语法
  18. jedis连接池参数minEvictableIdleTimeMillis和softMinEvictableIdleTimeMillis探索
  19. mysql手工注入总结
  20. Python day2_int以及string的常见方法1_笔记

热门文章

  1. Linux进程的创建函数fork()及其fork内核实现解析【转】
  2. css 水平、垂直居中
  3. linux系统磁盘挂载
  4. supervisor 的使用
  5. Oracle数据库,基础知识
  6. vmware linux虚拟机连接ip设置
  7. JS中firstChild,lastChild,nodeValue属性
  8. linux shell 正则表达式(BREs,EREs,PREs)的比较
  9. 修改input中的placeholder属性的颜色
  10. asp.net传多个值到其它页面的方法