题目链接: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

Problem Description
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
 
Input
包括多个测试实例,每个测试实例包括2整数m,n和m*n个非负数(m<=50,n<=50)
 
Output
对于每个测试实例,输出可能取得的最大的和
 
Sample Input
3 3
75 15 21
75 15 28
34 70 5
 
Sample Output
188
 
Author
ailyanlu
 
Source

题解:

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) —— 二分图点带权最大独立集、最小割最大流的更多相关文章

  1. HDU1565 方格取数(1) —— 状压DP or 插头DP(轮廓线更新) or 二分图点带权最大独立集(最小割最大流)

    题目链接:https://vjudge.net/problem/HDU-1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory L ...

  2. hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)

    /** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...

  3. hdu1569 方格取数 求最大点权独立集

    题意:一个方格n*m,取出一些点,要求两两不相邻,求最大和.思路:建图,相邻的点有一条边,则建立了一个二分图,求最大点权独立集(所取点两两无公共边,权值和最大),问题转化为求总权和-最小点权覆盖集(点 ...

  4. BZOJ 1475 方格取数(二分图最大点权独立集)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1475 [题目大意] 给出一个n*n的方格,从中取一些不相邻的数字,使得和最大 [题解] ...

  5. 洛谷 - P2774 - 方格取数问题 - 二分图最大独立点集 - 最小割

    https://www.luogu.org/problemnew/show/P2774 把两个相邻的节点连边,这些边就是要方便最小割割断其他边存在的,容量无穷. 这种类似的问题的话,把二分图的一部分( ...

  6. luogu2774 方格取数问题 二分图最小权点覆盖集

    题目大意:在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,输出这些数之和的最大值. 思路:这种各个点之间互相排斥求最大值的题,往往需要利 ...

  7. Luogu_2774 方格取数问题

    Luogu_2774 方格取数问题 二分图最小割 第一次做这种题,对于某些强烈暗示性的条件并没有理解到. 也就是每一立刻理解到是这个图是二分图. 为什么? 横纵坐标为奇数的只会和横纵坐标为偶数的相连. ...

  8. HDU 1569 方格取数(2)

    方格取数(2) Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 15 ...

  9. 【最小割/二分图最大独立集】【网络流24题】【P2774】 方格取数问题

    Description 给定一个 \(n~\times~m\) 的矩阵,每个位置有一个正整数,选择一些互不相邻的数,最大化权值和 Limitation \(1~\leq~n,~m~\leq~100\) ...

随机推荐

  1. cf711E ZS and The Birthday Paradox

    ZS the Coder has recently found an interesting concept called the Birthday Paradox. It states that g ...

  2. Failed building wheel for Twisted

    在安装scrapy框架的过程中,pip install scrapy 出现报错信息: building 'twisted.test.raiser' extension error: Microsoft ...

  3. 表单禁用复制、粘贴、及右击菜单(contextmenu、oncopy、oncut、onpaste、onselectstart)

    禁用右键菜单,可以使用oncontextmenu属性: <textarea oncontextmenu="return false"></textarea> ...

  4. ElasticSearch聚合aggs入门

    Elasticsearch是一款功能强大的开源软件,不仅可以检索排序,还可以对文档进行更复杂的操作--聚合. 1.单值聚合 Sum求和,dsl参考如下: { "size": 0, ...

  5. BZOJ4723: [POI2017]Flappy Bird

    $n \leq 500000$个水管,每秒横坐标加一,纵坐标如果你点击就+1否则-1,问从$(0,0)$飞到$m$处最少点多少次,或者说明无解. 如果能飞到某个水管的高度区间$[L,R]$,那么答案肯 ...

  6. Bootstrap开启模态框后对数据处理(标记模态框的开启与关闭状态)

    JS用全局变量标记状态,方法中动态修改全局变量以标记状态是一个重要思想. 需求:组合条件查询数据,查询完之后填充到模态框中,开启模态框,模态框中有组合条件查询,此时查询只需要更新模态框表格数据不需要开 ...

  7. 洛谷——P1057 传球游戏

    P1057 传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹 ...

  8. raspi扩展板

    1.Ciseco Slice 2.Adafruit(Plate) 3.Fen的Gertboard:(详见F盘下的使用手册) 12个缓冲输入输出端口 LED状态指示灯 3个按钮开关 6个开路集成电极 1 ...

  9. 关于PDF的读取与绘制

    本文方法参考了:官方文档.见A function that draw a PDF page的代码部分: void MyDisplayPDFPage (CGContextRef myContext, s ...

  10. 【Hibernate】(2)Hibernate配置与session、transaction

    1. Hibernate经常使用配置 使用hibernate.default_schema属性能够让全部生成的表都带一个指定的前缀. 2. session简单介绍 不建议直接使用jdbc的connec ...