博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【网络流24题】方格取数问题
阅读量:4568 次
发布时间:2019-06-08

本文共 2373 字,大约阅读时间需要 7 分钟。

P1528 - 【网络流24题】方格取数问题

Description

在一个有m * n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。

Input

第1 行有2 个正整数m和n,分别表示棋盘的行数和列数。

接下来的m行,每行有n个正整数,表示棋盘方格中的数。

Output

将取数的最大总和输出

Sample Input

3 3

1 2 3
3 2 3
2 3 1

Sample Output

11

 

将每个点和它相邻的点标记为不同的颜色,然后把白点和S相连,黑点和T相连,容量为这个点的权值。
然后把每个白点和它相邻的黑点相连,容量为inf。
然后问题就转化为求二分图最大点权独立集。
根据某个定理,答案就等于总权值减去最小割。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 1999999999using namespace std;struct data{ int nex,to,w;}e[12000];int head[1000],edge=-1;int f[32][32],a[32][32],id[32][32],lev[1000];void add(int from,int to,int w){ e[++edge].nex=head[from]; e[edge].to=to; e[edge].w=w; head[from]=edge;}inline bool bfs(int s,int t){ queue
q; q.push(s); memset(lev,0,sizeof(lev)); lev[s]=1; while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=e[i].nex) if(e[i].w>0 && !lev[e[i].to]){ lev[e[i].to]=lev[u]+1; q.push(e[i].to); if(e[i].to==t) return 1; } } return 0;}int dfs(int s,int t,int k){ if(s==t) return k; int tag=0; for(int i=head[s];i!=-1;i=e[i].nex) if(e[i].w>0 && lev[e[i].to]==lev[s]+1){ int d=dfs(e[i].to,t,min(k-tag,e[i].w)); e[i].w-=d; e[i^1].w+=d; tag+=d; if(tag==k) return tag; } return tag;}int dinic(int s,int t){ int flow=0; while(bfs(s,t)) flow+=dfs(s,t,inf); return flow;}int main(){ freopen("!.in","r",stdin); freopen("!.out","w",stdout); memset(head,-1,sizeof(head)); int n,m;scanf("%d%d",&n,&m); int s=0,t=n*m+1,tot=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]),tot+=a[i][j]; f[1][1]=1; for(int i=2;i<=m;i++) f[1][i]=f[1][i-1]^1; for(int i=2;i<=n;i++) for(int j=1;j<=m;j++) f[i][j]=f[i-1][j]^1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) id[i][j]=(i-1)*m+j; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ int k=id[i][j]; if(f[i][j]){ add(s,k,a[i][j]),add(k,s,0); if(i-1>0) add(k,id[i-1][j],inf),add(id[i-1][j],k,0); if(i+1<=n) add(k,id[i+1][j],inf),add(id[i+1][j],k,0); if(j-1>0) add(k,id[i][j-1],inf),add(id[i][j-1],k,0); if(j+1<=m) add(k,id[i][j+1],inf),add(id[i][j+1],k,0); } else add(k,t,a[i][j]),add(t,k,0); } printf("%d",tot-dinic(s,t)); return 0;}

 

转载于:https://www.cnblogs.com/pantakill/p/6613464.html

你可能感兴趣的文章
.NET中使用嵌入的资源
查看>>
javascript 的 appendChild用法
查看>>
企业建站美工参考
查看>>
Android day01
查看>>
基于Karma和Jasmine的angular自动化单元测试
查看>>
343. Integer Break
查看>>
存储过程和存储函数区别
查看>>
第二次结对编程 微软学术搜索
查看>>
项目中遇到的IE8浏览器访问页面过慢问题
查看>>
【转】MFC 程序入口和执行流程
查看>>
c++编程中的后缀
查看>>
从原型链看DOM--Document类型
查看>>
解决方案是什么
查看>>
Spring Bean引用例子
查看>>
您访问的URL地址不被允许。
查看>>
docker 初探之简单安装 ----Windows10
查看>>
UI基础篇之UIScrollView
查看>>
vc 网络编程(socket)
查看>>
tex中把参考文献标题删除
查看>>
Linux下NFS服务器的搭建与配置
查看>>