HDU1569 方格取数(2) —— 二分图点带权最大独立集、最小割最大流
题目链接:https://vjudge.net/problem/HDU-1569
方格取数(2)
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6876 Accepted Submission(s): 2198
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
75 15 21
75 15 28
34 70 5
题解:
1.将n*m的格子建模成二分图。
2.在二分图的基础上添加源点S和汇点T, 然后从S向所有X集合中的点连一条边, 所有Y集合中的点向T连一条边, 容量均为该点的权值。
3.X集合的结点与Y集合的结点之间的边的容量为无穷大。在此题中,如果是格子相邻,就需要连边,且是X-->Y。
4.因此,对于该图中的任意一个割, 将割中的边所对应的结点删掉,就是一个符合条件的解,权值和为所有权和减去割的容量。
5.根据4可得:只要求出最小割, 就能求出最大权值和独立集。
代码如下:
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <vector>
- #include <cmath>
- #include <queue>
- #include <stack>
- #include <map>
- #include <string>
- #include <set>
- using namespace std;
- typedef long long LL;
- const int INF = 2e9;
- const LL LNF = 9e18;
- const int mod = 1e9+;
- const int MAXM = 1e5+;
- const int MAXN = +;
- struct Edge
- {
- int to, next, cap, flow;
- }edge[MAXM];
- int tot, head[MAXN];
- int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN];
- void init()
- {
- tot = ;
- memset(head, -, sizeof(head));
- }
- void add(int u, int v, int w)
- {
- edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = ;
- edge[tot].next = head[u]; head[u] = tot++;
- edge[tot].to = u; edge[tot].cap = ; edge[tot].flow = ;
- edge[tot].next = head[v]; head[v] = tot++;
- }
- int sap(int start, int end, int nodenum)
- {
- memset(dep, , sizeof(dep));
- memset(gap, , sizeof(gap));
- memcpy(cur, head, sizeof(head));
- int u = pre[start] = start, maxflow = ,aug = INF;
- gap[] = nodenum;
- while(dep[start]<nodenum)
- {
- loop:
- for(int i = cur[u]; i!=-; i = edge[i].next)
- {
- int v = edge[i].to;
- if(edge[i].cap-edge[i].flow && dep[u]==dep[v]+)
- {
- aug = min(aug, edge[i].cap-edge[i].flow);
- pre[v] = u;
- cur[u] = i;
- u = v;
- if(v==end)
- {
- maxflow += aug;
- for(u = pre[u]; v!=start; v = u,u = pre[u])
- {
- edge[cur[u]].flow += aug;
- edge[cur[u]^].flow -= aug;
- }
- aug = INF;
- }
- goto loop;
- }
- }
- int mindis = nodenum;
- for(int i = head[u]; i!=-; i = edge[i].next)
- {
- int v=edge[i].to;
- if(edge[i].cap-edge[i].flow && mindis>dep[v])
- {
- cur[u] = i;
- mindis = dep[v];
- }
- }
- if((--gap[dep[u]])==)break;
- gap[dep[u]=mindis+]++;
- u = pre[u];
- }
- return maxflow;
- }
- int n, m, g[][];
- int main()
- {
- while(scanf("%d%d", &n, &m)!=EOF)
- {
- int sum = ;
- for(int i = ; i<n; i++)
- for(int j = ; j<m; j++)
- scanf("%d", &g[i][j]), sum += g[i][j];
- int start = n*m, end = n*m+;
- init();
- for(int i = ; i<n; i++)
- for(int j = ; j<m; j++)
- {
- if((i+j)%)
- {
- add(start, i*m+j, g[i][j]);
- if(i!=) add(i*m+j, (i-)*m+j, INF);
- if(i!=n-) add(i*m+j, (i+)*m+j, INF);
- if(j!=) add(i*m+j, i*m+j-, INF);
- if(j!=m-) add(i*m+j, i*m+j+, INF);
- }
- else
- add(i*m+j, end, g[i][j]);
- }
- sum -= sap(start, end, n*m+);
- printf("%d\n", sum);
- }
- }
HDU1569 方格取数(2) —— 二分图点带权最大独立集、最小割最大流的更多相关文章
- HDU1565 方格取数(1) —— 状压DP or 插头DP(轮廓线更新) or 二分图点带权最大独立集(最小割最大流)
题目链接:https://vjudge.net/problem/HDU-1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
/** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...
- hdu1569 方格取数 求最大点权独立集
题意:一个方格n*m,取出一些点,要求两两不相邻,求最大和.思路:建图,相邻的点有一条边,则建立了一个二分图,求最大点权独立集(所取点两两无公共边,权值和最大),问题转化为求总权和-最小点权覆盖集(点 ...
- BZOJ 1475 方格取数(二分图最大点权独立集)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1475 [题目大意] 给出一个n*n的方格,从中取一些不相邻的数字,使得和最大 [题解] ...
- 洛谷 - P2774 - 方格取数问题 - 二分图最大独立点集 - 最小割
https://www.luogu.org/problemnew/show/P2774 把两个相邻的节点连边,这些边就是要方便最小割割断其他边存在的,容量无穷. 这种类似的问题的话,把二分图的一部分( ...
- luogu2774 方格取数问题 二分图最小权点覆盖集
题目大意:在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,输出这些数之和的最大值. 思路:这种各个点之间互相排斥求最大值的题,往往需要利 ...
- Luogu_2774 方格取数问题
Luogu_2774 方格取数问题 二分图最小割 第一次做这种题,对于某些强烈暗示性的条件并没有理解到. 也就是每一立刻理解到是这个图是二分图. 为什么? 横纵坐标为奇数的只会和横纵坐标为偶数的相连. ...
- HDU 1569 方格取数(2)
方格取数(2) Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 15 ...
- 【最小割/二分图最大独立集】【网络流24题】【P2774】 方格取数问题
Description 给定一个 \(n~\times~m\) 的矩阵,每个位置有一个正整数,选择一些互不相邻的数,最大化权值和 Limitation \(1~\leq~n,~m~\leq~100\) ...
随机推荐
- 空指针问题(java.lang.NullPointerException)
在Java中对值为null的指针调用任何方法,就会引发空指针异常(java.lang.NullPointerException).空指针异常绝对是Java中最难查找和调试的一种异常,你永远无法得到任何 ...
- ReSharper7.1.25.234 注册机
经常用vs做开发的人都知道,ReSharper是vistual studio必备插件之一.他的智能提示,智能感知,.net底层方法查看,测试等都非常方便,给程序员带来了巨大的效率. 但众所周知ReSh ...
- oracle怎么查看表空间里有哪些表
select TABLE_NAME,TABLESPACE_NAME from dba_tables where TABLESPACE_NAME='表空间名'; 注意:表空间名要大写
- Android数据存储之SQLite数据库
Android数据存储 之SQLite数据库简介 SQLite的相关知识,并结合Java实现对SQLite数据库的操作. SQLite是D.Richard Hipp用C语言编写的开源嵌入式数据库引擎. ...
- 树莓派学习笔记——I2C设备载入和速率设置
原文:http://blog.csdn.net/xukai871105/article/details/18234075 1.载入设备 方法1——临时载入设备 sudo modprobe -r i2c ...
- IntelliJ IDEA常用统一设置(Linux/Mac/Windows)
前言:如果说VS是宇宙超级无敌第一大开发工具,那么IDEA是当之无愧的第二大开发工具,将来有机会把VS干掉. 说明:除了以下说明的配置地方外,其它尽量保持默认,这样有利于团队代码风格的统一. 运行VM ...
- go语言学习之路三:切片
前面讲了变量的有关知识,这里对于其他的数据类型就不多作介绍,(和C差不多),因此重点来讨论下切片. 一.切片是引用类型,这里要稍微介绍两个概念:值类型,构造类型和引用类型 1.值类型:是一种由类型的实 ...
- cut printf awk sed grep笔记
名称 作用 参数 实例 cut 截取某列,可指定分隔 -f 列号 -d 分隔符 cut -d ":" -f 1, 3 /etc/passwd 截取第一列和第三列 printf pr ...
- Linux内核配置选项
http://blog.csdn.net/wdsfup/article/details/52302142 http://www.manew.com/blog-166674-12962.html Gen ...
- 【SQL Server 学习系列】-- 获取字符串中出现某字符的次数及字符某次出现的下标
) = '1_BB_CC_DD_AA_EE_YY_WW_HH_GG' --// 1. 获取下划线在字符串中出现的次数 SELECT LEN(@Str) - LEN(REPLACE(@Str, '_', ...