题意:

n,m<=30

思路:

【问题分析】

二分图点权最大独立集,转化为最小割模型,从而用最大流解决。

【建模方法】

首先把棋盘黑白染色,使相邻格子颜色不同,所有黑色格子看做二分图X集合中顶点,白色格子看做Y集合顶点,建立附加源S汇T。

1、从S向X集合中每个顶点连接一条容量为格子中数值的有向边。

2、从Y集合中每个顶点向T连接一条容量为格子中数值的有向边。

3、相邻黑白格子Xi,Yj之间从Xi向Yj连接一条容量为无穷大的有向边。

求出网络最大流,要求的结果就是所有格子中数值之和减去最大流量。

【建模分析】

这是一个二分图最大点权独立集问题,就是找出图中一些点,使得这些点之间没有边相连,这些点的权值之和最大。独立集与覆盖集是互补的,求最大点权独立集可以转化为求最小点权覆盖集(最小点权

支配集)。最小点权覆盖集问题可以转化为最小割问题解决。结论:最大点权独立集 = 所有点权 - 最小点权覆盖集 = 所有点权 - 最小割集 = 所有点权 - 网络最大流。

对于一个网络,除去冗余点(不存在一条ST路径经过的点),每个顶点都在一个从S到T的路径上。割的性质就是不存在从S到T的路径,简单割可以认为割边关联的非ST节点为割点,而在二分图网络流模

型中每个点必关联到一个割点(否则一定还有增广路,当前割不成立),所以一个割集对应了一个覆盖集(支配集)。最小点权覆盖集就是最小简单割,求最小简单割的建模方法就是把XY集合之间的变容

量设为无穷大,此时的最小割就是最小简单割了。

有关二分图最大点权独立集问题,更多讨论见《最小割模型在信息学竞赛中的应用》作者胡伯涛。

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<ll,ll>P;
#define N 100010
#define M 1000000
#define INF 1e9
#define fi first
#define se second
#define MP make_pair
#define pb push_back
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const ll MOD=1e9+,inv2=(MOD+)/;
double eps=1e-;
int dx[]={-,,,};
int dy[]={,,-,}; int head[N],vet[N],len[N],nxt[N],dis[N],
a[][],b[][],num[][],s,S,T,tot; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void add(int a,int b,int c)
{
nxt[++tot]=head[a];
vet[tot]=b;
len[tot]=c;
head[a]=tot; nxt[++tot]=head[b];
vet[tot]=a;
len[tot]=;
head[b]=tot;
} bool bfs()
{
queue<int>q;
rep(i,,s) dis[i]=-;
q.push(S),dis[S]=;
while(!q.empty())
{
int u=q.front();
q.pop();
int e=head[u];
while(e)
{
int v=vet[e];
if(len[e]&&dis[v]==-)
{
dis[v]=dis[u]+;
q.push(v);
}
e=nxt[e];
}
}
return dis[T]!=-;
} int dfs(int u,int aug)
{
if(u==T) return aug;
int e=head[u],val=,flow=;
while(e)
{
int v=vet[e];
if(len[e]&&dis[v]==dis[u]+)
{
int t=dfs(v,min(len[e],aug));
if(!t)
{
e=nxt[e];
continue;
}
flow+=t;
aug-=t;
len[e]-=t;
len[e^]+=t;
if(!aug) break;
}
e=nxt[e];
}
if(!flow) dis[u]=-;
return flow;
} int maxflow()
{
int res=;
while(bfs()) res+=dfs(S,INF);
return res;
} int main()
{
int n=read(),m=read();
int ans=;
rep(i,,n)
rep(j,,m)
{
a[i][j]=read();
ans+=a[i][j];
} tot=;
s=;
rep(i,,n)
rep(j,,m) num[i][j]=++s; rep(i,,n)
rep(j,,m)
if((i+j+)&)
rep(k,,)
{
int x=i+dx[k],y=j+dy[k];
if(x>&&x<=n&&y>&&y<=m) add(num[i][j],num[x][y],INF);
}
S=++s,T=++s;
rep(i,,n)
rep(j,,m)
if((i+j+)&) add(S,num[i][j],a[i][j]);
else add(num[i][j],T,a[i][j]);
ans-=maxflow();
printf("%d\n",ans);
return ;
}

最新文章

  1. Linux学习之CentOS(二十)--CentOS6.4下修改MySQL编码方法
  2. Android 贝塞尔曲线库
  3. padding和margin的区别
  4. 第九回 Microsoft.Practices.Unity.Interception实现基于数据集的缓存(针对六,七,八讲的具体概念和配置的解说)
  5. 【java】之读取InputStream流
  6. 【图文详解】scrapy爬虫与动态页面——爬取拉勾网职位信息(2)
  7. C# 线程(六):定时器
  8. tyvj 1057 dp 变形背包
  9. 异构平台同步(Mysql到Oracle)
  10. 进程内外的session
  11. Python学习——struct模块的pack、unpack示例
  12. make clean、make mrproer、make distclean
  13. es6模板字符串 问题记录
  14. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(1)-前言与目录(持续更新中...)
  15. hdu1015(Safecracker )
  16. 静态变量和Session
  17. pm2模块编写入门
  18. 每天学习SQL
  19. ALTER SEQUENCE 导致 REPLICAT 延时
  20. OWASP TOP 10 2017中文译文

热门文章

  1. python-应用OpenCV和Python进行SIFT算法的实现
  2. java文件编译后,出现xx$1.class的原因
  3. [19/10/16-星期四] Python中的文件操作
  4. Mybatis-学习笔记(N)mybatis-generator 生成DAO、Mapper、entity
  5. Django使用Celery进行异步任务
  6. ETL工具Kettle使用以及与Java整合实现数据清洗
  7. 小程序中页面兼容h5标签的解析
  8. VLAN原理详解[转载] 网桥--交换机---路由器
  9. numpy中的range()
  10. PAT Basic 1028 人口普查 (20 分)