HDU 1569 方格取数(2)(最大流最小割の最大权独立集)
Description
Input
Output
题目大意:这么短还中文就没大意了,唯一要注意的就是输入的第一个是行第二个是列……
思路:这题为最大权独立集(所选的点之间都没有边)。建立一个最大流的二分图,i+j为偶数的放左边,源点S连一条边到它,容量为格子里的数,其余放右边,连一条边到汇点T,容量还是格子里的数,相邻的都从左到右连一条边,容量为无穷大。所有数字之和减去最大流即为答案。
小证明:这样构图求出的最大流为最小权覆盖集(所有边至少被一个点覆盖),详见POJ 3308 Paratroopers(最大流最小割の最小点权覆盖)
而最小权覆盖集与最大权独立集是对偶图,把最小权覆盖集里的点都取反,就可以得到一个最大权独立集,所以总权 = 最小权覆盖集 + 最大权独立集。详见二分图中的对偶问题
代码(15MS):
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; const int MAXN = ;
const int MAXE = ;
const int INF = 0x3fff3fff; struct SAP {
int head[MAXN], dis[MAXN], pre[MAXN], cur[MAXN], gap[MAXN];
int to[MAXE], next[MAXE], flow[MAXE];
int n, st, ed, ecnt; void init() {
memset(head, , sizeof(head));
ecnt = ;
} void add_edge(int u, int v, int c) {
to[ecnt] = v; flow[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
//printf("%d->%d flow = %d\n", u, v, c);
} void bfs() {
memset(dis, 0x3f, sizeof(dis));
queue<int> que; que.push(ed);
dis[ed] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
++gap[dis[u]];
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(flow[p ^ ] && dis[v] > n) {
dis[v] = dis[u] + ;
que.push(v);
}
}
}
} int Max_flow(int ss, int tt, int nn) {
st = ss; ed = tt; n = nn;
int ans = , minFlow = INF, u;
for(int i = ; i <= n; ++i) {
cur[i] = head[i];
gap[i] = ;
}
u = pre[st] = st;
bfs();
while(dis[st] < n) {
bool flag = false;
for(int &p = cur[u]; p; p = next[p]) {
int &v = to[p];
if(flow[p] && dis[u] == dis[v] + ) {
flag = true;
minFlow = min(minFlow, flow[p]);
pre[v] = u;
u = v;
if(u == ed) {
ans += minFlow;
while(u != st) {
u = pre[u];
flow[cur[u]] -= minFlow;
flow[cur[u] ^ ] += minFlow;
}
minFlow = INF;
}
break;
}
}
if(flag) continue;
int minDis = n - ;
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(flow[p] && minDis > dis[v]) {
minDis = dis[v];
cur[u] = p;
}
}
if(--gap[dis[u]] == ) break;
gap[dis[u] = minDis + ]++;
u = pre[u];
}
return ans;
}
} G; int n, m;
int mat[][]; int main() {
while(scanf("%d%d", &n, &m) != EOF) {
for(int i = ; i <= n; ++i)
for(int j = ; j <= m; ++j) scanf("%d", &mat[i][j]);
G.init();
int ss = n * m + , tt = n * m + ;
int cnt = , sum = ;
for(int i = ; i <= n; ++i) {
for(int j = ; j <= m; ++j) {
++cnt; sum += mat[i][j];
if((i + j) & ) {
G.add_edge(ss, cnt, mat[i][j]);
if(j != ) G.add_edge(cnt, cnt - , INF);
if(i != ) G.add_edge(cnt, cnt - m, INF);
if(j != m) G.add_edge(cnt, cnt + , INF);
if(i != n) G.add_edge(cnt, cnt + m, INF);
}
else G.add_edge(cnt, tt, mat[i][j]);
}
}
printf("%d\n", sum - G.Max_flow(ss, tt, tt));
}
}
HDU 1569 方格取数(2)(最大流最小割の最大权独立集)的更多相关文章
- HDU 1569 方格取数(2) (最小割)
方格取数(2) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)
HDU 1565 方格取数(1) 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的 ...
- HDU 1569 方格取数(2)
方格取数(2) Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 15 ...
- HDU 1569 - 方格取数(2) - [最大点权独立集与最小点权覆盖集]
嗯,这是关于最大点权独立集与最小点权覆盖集的姿势,很简单对吧,然后开始看题. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569 Time Limi ...
- HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]
题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...
- HDU 1565 1569 方格取数(最大点权独立集)
HDU 1565 1569 方格取数(最大点权独立集) 题目链接 题意:中文题 思路:最大点权独立集 = 总权值 - 最小割 = 总权值 - 最大流 那么原图周围不能连边,那么就能够分成黑白棋盘.源点 ...
- [HDU 1565+1569] 方格取数
HDU 1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- HDU 1565&1569 方格取数系列(状压DP或者最大流)
方格取数(2) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- HDU 1565 方格取数(1) 轮廓线dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) ...
随机推荐
- stl学习之namespace
一.为什么需要命名空间(问题提出) 命名空间是ANSIC++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突. 在 C语言中定义了3个层次的作用域,即文件(编译单元).函数和复合语句.C++ ...
- 浅谈CSS高度坍塌
高度坍塌情况: 当父元素没有设置高度,且子元素块都向左(右)浮动起来,那么父元素就会出现坍塌的现象. 解决办法: 在父元素包含块中加一个div: 优点:兼容性强,适合初学者. 缺点:不利于优化. 方法 ...
- Git-2.15.1.2-64-bit安装
方法/步骤 我们在百度搜索git,然后在git的官网上找到git的下载页面,如下图所示.在首页在Downloads处选择下载Windows版本,当然您可以根据需求下载其他版本的安装文件. ...
- Yii2 yiisoft/mongodb 手动安装
手动将yiisoft/mongodb下载到vendor/yiisoft目录(注意约束条件). 在vendor/yiisoft/extensions.php 中添加 'yiisoft/yii2-mong ...
- VUE通过索引值获取数据不渲染的问题
问题:vue里面当通过索引值获取数据时,ajax数据成功返回,但是在火狐下不渲染 解决:
- 大数据学习--day09(this、static)
this.static this 关键字 类不可以定义 this 属性 , 但是每个类都有一个 隐藏起来的 this 属性 . 每个对象被创建了 , 都会给其属性分配空间 , 也会给 this ...
- sublime text 3安装 package control 插件的方法
自动安装的方法 - 快捷键ctrl+` 或者View->Show Console,输入如下代码 import urllib.request,os;pf='Package Control.sub ...
- hive新手学习随笔
一.回顾 1.hive基于Hadoop的(存储HDFS,计算MR) 2.sql on hadoop概念 ->简化开发的操作 ->提升 ...
- A1041
输入n个数,找出第一个只出现一次的数,输出它. 如果没有,输出none. 思路: 将输入的数值作为HashTable的数组下标即可. #include<cstdio> ], hashTab ...
- 在XAML中为ItemsControl定义分组,适合mvvm绑定
可以先参考一下这个文章: http://www.cnblogs.com/zoexia/archive/2014/11/30/4134012.html step0: 先展示一下最简陋的界面: 上图是一个 ...