方格取数

题目描述

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

输入输出格式

输入格式:

第 1 行有 2 个正整数 m 和 n,分别表示棋盘的行数和列数。接下来的 m 行,每行有 n 个正整数,表示棋盘方格中的数。

输出格式:

程序运行结束时,将取数的最大总和输出

题目链接

这道题的题意还是比较好理解的,就是不能取相邻的两个数,使所有取出来的数的总和最大。。

嗯,先不要急着想搜索、暴力或贪心(虽然有可能可以过,如果可以,欢迎指教),这题可是出自网络流24题的呀。

所以肯定是用网络流    我们也可以用网络流来做。

首先,也是最关键的,这题如何建图?

我们可以这样想:

把格子染成黑白两色,形如下图:  有点丑。。好吧,不止一点

其实黑白两色也可以反过来,不过这不是重点。

我们把每个格标个号:

然后我们可以把格子抽象成一个点,然后分开:

最后就是连边:

左边那个蓝蓝的是源点,然后那个白色的圈是汇点。

从源点连向黑点的边的权值(容量)是那个黑点的值,然后从白点连向汇点的边也是权值。

最后中间那一大坨是。。。。嗯,边的两边的点时候不能同时选的(因为有公共边),边权是INF(尽量大)。

我们要求的是什么呢,没错,选出来的所有点的权值最大…… 这TMD和这图有什么关系啊?

别心急,这题应该是要求最大点权独立集(注意:是点权),就等于所有点的值减去最小点权覆盖集,就是减去最小割(最大流),然后我们就可以开心地写代码了。

可能有些同学并不理解最后一句话是什么意思(其实一开始我也不理解)。

其实是这样的,我们相当与把点权转换为了边权,我们的目的是断开一些边,使得没有路径从源点到达汇点(为了满足题目的限制条件吗),然后我们要使断开的边的权值之和最小(断开的边就相当于是不选那个点,就是剩下的边权之和最大->这就是我们要求的答案嘛),乍一看,这不就是最小割吗?因为最小割=最大流,所以我们可以跑一遍最大流,然后用总的边权减去最大流就是我们的答案了,是不是很棒棒。

总结:做完这题,我对网络流的理解又加深了一层。我们要巧妙的利用网络流的建模技巧(这也是网络流的精髓),把问题转换为可以用网络流解决的问题,要多刷题,刷好题,才能掌握技巧。

上代码:

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1000005;
const int MAXM=1000005;
int d[MAXN],n,m,p[MAXN],eid,S,T,x[MAXN],y[MAXN],z[MAXN],a[105][105],sz,sum;
struct A{  //灰常正常的最大流(Dinic)int v,c,next;
}e[MAXM];
void init(){memset(p,-1,sizeof(p));eid=0;
}
void add(int u,int v,int c){e[eid].v=v;e[eid].c=c;e[eid].next=p[u];p[u]=eid++;
}
void insert(int u,int v,int c){add(u,v,c);add(v,u,0);
}
int bfs(){memset(d,-1,sizeof(d));queue<int>q;d[S]=0;q.push(S);while(!q.empty()){int u=q.front();q.pop();for(int i=p[u];i!=-1;i=e[i].next){int v=e[i].v;if(e[i].c>0&&d[v]==-1){d[v]=d[u]+1;q.push(v); }}}return (d[T]!=-1);
}
int dfs(int u,int flow){ if(u==T) return flow;int ret=0;for(int i=p[u];i!=-1;i=e[i].next){int v=e[i].v;if(e[i].c>0&&d[v]==d[u]+1){int tmp=dfs(v,min(flow,e[i].c));e[i].c-=tmp;e[i^1].c+=tmp;flow-=tmp;ret+=tmp;if(!flow) break;}}if(!ret) d[u]=-1;return ret;
}
int Dinic(){int ret=0;while(bfs()){ret+=dfs(S,INF);}return ret;
}
int main(){    //以下开始码风突变(中了yjq的膜法)init();scanf("%d%d", &m, &n);S=0;T=n*m+1;//建立源点和汇点for(int i = 1; i <= m; i++){for(int j = 1; j <= n; j++){scanf("%d", &a[i][j]);sum += a[i][j];sz ++;if((i + j) % 2){insert(S, sz, a[i][j]);//连向源点if(j < n) insert(sz, sz + 1, INF);//把有限制条件的连起来,边权注意要尽量大if(j > 1) insert(sz, sz - 1, INF);if(i < m) insert(sz, sz + n, INF);if(i > 1) insert(sz, sz - n, INF);} else {insert(sz,T,a[i][j]);//连向汇点}}} printf("%d",sum - Dinic());//总的边权 - 最大流(最小割)return 0;
}

方格取数问题(网络流24题之一)相关推荐

  1. 734. [网络流24题] 方格取数问题 二分图点权最大独立集/最小割/最大流

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

  2. 最小割 ---- 二分图最大独立集(集合冲突模型) ---- 骑士共存 方格取数(网络流24题)

    二分图独立集 定理: 二分图最大独立集=n - 二分图最大匹配 其实二分图独立集是特殊的一种最大权闭合子图.我们根据上文"收益"的思想,把选某个点的收益看为1,左部节点为正权点,右 ...

  3. 【网络流24题】I、 方格取数问题(二分图的最大独立集/最小割)

    I. 方格取数问题(二分图的最大独立集/最小割) [问题分析] 二分图点权最大独立集,转化为最小割模型,从而用最大流解决. [建模方法] 首先把棋盘黑白染色,使相邻格子颜色不同,所有黑色格子看做二分图 ...

  4. 线性规划与网络流24题●09方格取数问题13星际转移问题

    ●(做codevs1908时,发现测试数据也涵盖了1907,想要一并做了,但因为"技术"不佳,搞了一上午) ●09方格取数问题(codevs1907  方格取数3) 想了半天,也没 ...

  5. 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)

    HDU 1565 方格取数(1) 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和 ...

  6. XTU 二分图和网络流 练习题 C. 方格取数(1)

    C. 方格取数(1) Time Limit: 5000ms Memory Limit: 32768KB 64-bit integer IO format: %I64d      Java class ...

  7. [网络流][最大点权独立集] 方格取数

    预备知识: 点覆盖集:无向图G的一个点集,使得该图中所有边都至少有一个端点在该集合内. 最小点权覆盖集:在带点权无向图G中,点权之和最小的覆盖集. 点独立集:无向图G的一个点集,使得任两个在该集合中的 ...

  8. 网络流建模方法(四)—— 互不攻击问题 洛谷 P3353 骑士共存问题 (附 洛谷 P2774 方格取数问题)

    网络流建模方法(四)互不攻击问题,或者说是共存问题, 这类题目看起来有点像二分图匹配,这类题目我们就是建一个二分图然后跑最大流 还是先说题目洛谷P3353 题目描述 在一个 nn个方格的国际象棋棋盘上 ...

  9. hdu 3657 最大点权独立集变形(方格取数的变形最小割,对于最小割建图很好的题)...

    转载:http://blog.csdn.net/cold__v__moon/article/details/7924269 /* 这道题和方格取数2相似,是在方格取数2的基础上的变形.方格取数2解法: ...

  10. CSP2020-J2 题解 —— D题:方格取数

    题目相关 题目链接 目前还没有官方的题目,本题目来自洛谷,https://www.luogu.com.cn/problem/P7074?contestId=37027. 题目描述 设有 n×m 的方格 ...

最新文章

  1. python编程基础之二十
  2. Qt Creator分析QML应用程序
  3. EJBCA 6 通过调用WebService接口增加用户并获取证书
  4. 面向对象 - 继承/组合 - 总结
  5. 美检方或起诉刘强东;百度对呛微信规则;澳洲调查 Facebook | 极客头条
  6. JavaWeb——eclipse与tomcat环境配置
  7. size()和 strlen区别
  8. R中的子集选取运算符
  9. Java开发必备软件安装大全(建议学生党初学Java开发收藏)
  10. 性能监控之 Linux 命令 top、vmstat、iostat、free、iftop 基础
  11. 电动车结构及其工作原理
  12. 淘宝客赚钱方式及怎么入门和推广引流详解
  13. DES算法的加解密原理(详细算法+样例Demo)
  14. 从0到1:微信小程序自选股项目回忆录
  15. css3渐变—渐变_玩渐变
  16. Python基础入门之切片
  17. Python模块介绍使用:EasyOCR快速实现图片文字识别
  18. 一年中最后一个月的最后一天说说_最后一天的说说_最后一天的心情说说大全...
  19. 【图片新闻】近日一架美军F/A-18E战斗机在星球大战峡谷附近坠毁
  20. 目标检测论文解读复现之八:基于YOLOv5s的滑雪人员检测研究

热门文章

  1. 淘宝无人直播赚钱模式
  2. 陈强教授《机器学习及R应用》课程 第十三章作业
  3. 如何从0到1搭建业务架构?
  4. 【经典】产品人面试中的一些软回答~~
  5. ThinkPHP整合微信支付之发裂变红包
  6. balancap/SSD-Tensorflow使用及训练预测自己的数据集
  7. 微软ime日文输入法在假名输入模式下怎么快速输入英文
  8. 为什么群发邮件会退回:怎么做来避免邮件退回并提高群发邮件到达率
  9. 观察者模式(行为型)
  10. [java] 汇率换算器实现(3)