Description

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

Limitation

\(1~\leq~n,~m~\leq~100\)

Solution

由于数必须互不相邻,考虑二分图。

将矩阵染成二分图,相邻的格子连边,这样一条边的两个端点不能被同时选择,问题就被转化为了二分图上的最大带权独立集问题。

有关二分图的几个定理:

二分图最小无权点覆盖 = 二分图最大匹配

二分图最小无权边覆盖 = 总点数 - 二分图最大匹配

二分图最大无权独立集 = 总点数 - 二分图最大匹配

如果点带点 权,则源点向左部连边,容量为点权,右部向汇点连边,容量为点权,原边保留,容量无穷。

二分图最小权点覆盖 = 最小割

二分图最大权独立集 = 点权和 - 最小割

最小点权覆盖的证明与最大权闭合子图的证明类似,证明在这里,最大权独立集的证明需要 最大独立集 = 全集 - 最小点覆盖 的引理。

于是这题跑一个最小割就可以解决了。

Code

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif typedef long long int ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
int top=0;
do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
} const int maxn = 10010;
const int maxm = 105;
const int INF = 100000000; struct Edge {
int u, v, flow;
Edge *nxt, *bk; Edge(const int _u, const int _v, const int _flow, Edge* &h) {
this->u = _u; this->v = _v; this->flow = _flow; this->nxt = h; h = this;
}
};
Edge *hd[maxn], *fir[maxn];
inline void cont(const int _u, const int _v, const int _flow) {
auto u = new Edge(_u, _v, _flow, hd[_u]), v = new Edge(_v, _u, 0, hd[_v]);
(u->bk = v)->bk = u;
} int n, m, s, t, ans;
int MU[maxn], id[maxm][maxm], col[maxm][maxm], dist[maxn];
std::queue<int>Q; bool bfs();
int dfs(const int u, int canag);
void link(const int x, const int y); int main() {
freopen("1.in", "r", stdin);
qr(n); qr(m);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) {
qr(MU[id[i][j] = ++t]);
ans += MU[t];
}
s = ++t; ++t;
for (int i = 1; i <= n; ++i) {
if ((col[i][1] = col[i - 1][1] ^ 1))
link(i, 1);
else
cont(id[i][1], t, MU[id[i][1]]);
for (int j = 2; j <= m; ++j)
if ((col[i][j] = col[i][j - 1] ^ 1))
link(i, j);
else
cont(id[i][j], t, MU[id[i][j]]);
} while (bfs()) {
for (int i = 1; i <= t; ++i) fir[i] = hd[i];
ans -= dfs(s, INF);
} qw(ans, '\n', true);
return 0;
} bool bfs() {
memset(dist, 0, sizeof dist);
Q.push(s); dist[s] = 1;
while (!Q.empty()) {
int u = Q.front(); Q.pop();
for (auto e = hd[u]; e; e = e->nxt) if (e->flow > 0) {
int v = e->v;
if (dist[v]) continue;
dist[v] = dist[u] + 1;
Q.push(v);
}
}
return dist[t];
} int dfs(const int u, int canag) {
if ((u == t) || (!canag)) return canag;
int _f = 0;
for (auto &e = fir[u]; e; e = e->nxt) if (e->flow > 0) {
int v = e->v;
if (dist[v] != (dist[u] + 1)) continue;
int f = dfs(v, std::min(canag, e->flow));
e->flow -= f; e->bk->flow += f; _f += f;
if (!(canag -= f)) break;
}
return _f;
} void link(const int x, const int y) {
int u = id[x][y];
cont(s, u, MU[u]);
if (x > 1) cont(u, id[x - 1][y], INF);
if (y < m) cont(u, id[x][y + 1], INF);
if (y > 1) cont(u, id[x][y - 1], INF);
if (x < n) cont(u, id[x + 1][y], INF);
}

【最小割/二分图最大独立集】【网络流24题】【P2774】 方格取数问题的更多相关文章

  1. LibreOJ #6007. 「网络流 24 题」方格取数 最小割 最大点权独立集 最大流

    #6007. 「网络流 24 题」方格取数 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  2. Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流)

    Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流) Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从 ...

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

    ●(做codevs1908时,发现测试数据也涵盖了1907,想要一并做了,但因为“技术”不佳,搞了一上午) ●09方格取数问题(codevs1907  方格取数3) 想了半天,也没成功建好图: 无奈下 ...

  4. 【PowerOJ1744&网络流24题】方格取数问题(最小割)

    题意: n,m<=30 思路: [问题分析] 二分图点权最大独立集,转化为最小割模型,从而用最大流解决. [建模方法] 首先把棋盘黑白染色,使相邻格子颜色不同,所有黑色格子看做二分图X集合中顶点 ...

  5. 【刷题】LOJ 6007 「网络流 24 题」方格取数

    题目描述 在一个有 \(m \times n\) 个方格的棋盘中,每个方格中有一个正整数. 现要从方格中取数,使任意 \(2\) 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数 ...

  6. 【最小割】【网络流24题】【P2762】 太空飞行计划问题

    Description W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,-,Em},和进行这些实验需要使 ...

  7. P2774 方格取数问题(最小割)

    P2774 方格取数问题 一看题目便知是网络流,但由于无法建图.... 题目直说禁止那些条件,这导致我们直接建图做不到,既然如此,我们这是就要逆向思维,他禁止那些边,我们就连那些边. 我们将棋盘染色, ...

  8. P2774 方格取数问题 网络流

    题目: P2774 方格取数问题 题目背景 none! 题目描述 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大. ...

  9. P2774 方格取数问题 网络流重温

    P2774 方格取数问题 这个题目之前写过一次,现在重温还是感觉有点难,可能之前没有理解透彻. 这个题目要求取一定数量的数,并且这些数在方格里面不能相邻,问取完数之后和最大是多少. 这个很好的用了网络 ...

  10. P2774 方格取数问题(网络流)

    P2774 方格取数问题 emm........仔细一看,这不是最大权闭合子图的题吗! 取一个点$(x,y)$,限制条件是同时取$(x,y+1),(x,y-1),(x+1,y),(x-1,y)$,只不 ...

随机推荐

  1. zookeeper_节点数据版本号问题

    转自:Simba_cheng 更新节点数据的方法: 同步方法:Stat setData(final String path, byte data[], int version) 异步方法:void s ...

  2. 学员管理系统(SQLAlchemy 实现)

    一.业务逻辑 二.设计表结构 三.代码结构 start.py import os, sys sys.path.insert(0, os.path.dirname(os.path.dirname(os. ...

  3. nice和renice命令详解

    基础命令学习目录首页 进程调度是linux中非常重要的概念.linux内核有一套高效复杂的调度机制,能使效率极大化,但有时为了实现特定的要求,需要一定的人工干预.比如,你希望操作系统能分配更多的CPU ...

  4. Vue 列表渲染及条件渲染实战

    条件渲染 有时候我们要根据数据的情况,决定标签是否进行显示或者有其他动作.最常见的就是,表格渲染的时候,如果表格没有数据,就显示无数据.如果有数据就显示表格数据. Vue 帮我们提供了一个v-if的指 ...

  5. Thirteenth scrum meeting 2015/11/11

    发布bug整理集结: 手机用户体验优化优化: (1)主界面和课程界面的字体规格以及界面结构不同 (2)课程图片的大小格式不统一,造成美观下降 ( 3 )按钮的位置不美观 平板用户体验: (1)Tab键 ...

  6. 关于datatable的数据绑定问题

    最近做项目掉在数据绑定这个小坑里了,最后发现问题其实很简单,只是官方的文档描述可能不太清除导致的吧.首先贴上官网地址:http://www.datatables.club/ 关于这个插件的简单使用就不 ...

  7. C语言中的strstr函数

    转自:http://www.cnblogs.com/xy-kidult/archive/2012/12/25/2832460.html 早上翻<C和指针>,碰见一个子串查找问题,这个问题在 ...

  8. tomcat介绍

    Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由java语言编写,需要运行在jvm虚拟机中.之所以Java的应用 ...

  9. excel文件怎么使用php进行处理

    1.可以通过phpmyadmin导入csv文件 2.也可以直接使用php 处理已经将excel另存为.csv后缀的文件, 通过php专门处理csv文件的函数 如 fgetcsv() <?php ...

  10. mysql 函数示例(转)

    MySQL函数大全及用法示例 1.字符串函数ascii(str)   返回字符串str的第一个字符的ascii值(str是空串时返回0)  mysql> select ascii('2');   ...