最小割...二分染色然后把颜色不同的点的源汇反过来..然后就可以做了.

某个点(x,y):

S->Id(x,y)(回报), Id(x,y)->T(代价), Id(i,j)&&Id(相邻节点)->newId(i,j)(+oo), newId(i,j)->T(回报)

然后染色不同的点反过来就可以了.

初始时答案为2*∑回报, 这样每个点要么割掉1个回报,要么割掉2个回报, 要么割掉1回报+代价.都对应着每一种方案

--------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
 
using namespace std;
 
#define Id(x, y) ((x) * M + (y))
#define chk(x, y) (0 <= (x) && (x) < N && 0 <= (y) && (y) < M)
 
const int maxn = 5009;
const int INF = 1 << 30;
const int dx[4] = {-1, 0, 0, 1};
const int dy[4] = {0, 1, -1, 0};
 
inline int read() {
char c = getchar();
int ret = 0;
for(; !isdigit(c); c = getchar());
for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
return ret;
}
 
struct edge {
int to, cap;
edge *next, *rev;
} E[5000000], *pt = E, *head[maxn], *p[maxn], *cur[maxn];
 
inline void Add(int u, int v, int w) {
pt->to = v;
pt->cap = w;
pt->next = head[u];
head[u] = pt++;
}
inline void AddEdge(int u, int v, int w) {
Add(u, v, w);
Add(v, u, 0);
head[u]->rev = head[v];
head[v]->rev = head[u];
}
 
int N, M, S, T, V, ans;
int h[maxn], cnt[maxn];
 
void Solve() {
for(int i = 0; i < V; i++) cur[i] = head[i];
memset(cnt, 0, sizeof cnt);
memset(h, 0, sizeof h);
cnt[0] = V;
edge* e;
int Flow = 0;
for(int x = S, A = INF; h[S] < V; ) {
for(e = cur[x]; e; e = e->next)
if(e->cap && h[e->to] + 1 == h[x]) break;
if(e) {
A = min(A, e->cap);
cur[x] = p[e->to] = e;
if((x = e->to) == T) {
for(; x != S; x = p[x]->rev->to) {
p[x]->cap -= A;
p[x]->rev->cap += A;
}
Flow += A;
A = INF;
}
} else {
if(!--cnt[h[x]]) break;
h[x] = V;
for(e = head[x]; e; e = e->next) if(e->cap && h[e->to] + 1 < h[x]) {
h[x] = h[e->to] + 1;
cur[x] = e;
}
cnt[h[x]]++;
if(x != S)
x = p[x]->rev->to;
}
}
printf("%d\n", (ans << 1) - Flow);
}
 
void Init() {
N = read(); M = read();
V = N * M; S = V++; T = V++;
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++)
(i + j) & 1 ? AddEdge(Id(i, j), T, read()) : AddEdge(S, Id(i, j), read());
ans = 0;
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++) {
int v = read(), np = V++;
ans += v;
if((i + j) & 1) {
AddEdge(S, Id(i, j), v);
AddEdge(np, T, v);
AddEdge(Id(i, j), np, INF);
for(int k = 0; k < 4; k++) {
int x = i + dx[k], y = j + dy[k];
if(chk(x, y))
AddEdge(Id(x, y), np, INF);
}
} else {
AddEdge(Id(i, j), T, v);
AddEdge(S, np, v);
AddEdge(np, Id(i, j), INF);
for(int k = 0; k < 4; k++) {
int x = i + dx[k], y = j + dy[k];
if(chk(x, y))
AddEdge(np, Id(x, y), INF);
}
}
}
}
 
int main() {
Init();
Solve();
return 0;
}

--------------------------------------------------------------------------------

3774: 最优选择

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 96  Solved: 48
[Submit][Status][Discuss]

Description

小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的。一个点如果被选择了,那么可以得到Bij的回报,现在请你帮小N选一个最优的方案,使得回报-代价尽可能大。

Input

第一行两个正整数N,M表示方格图的长与宽。

接下来N行每行M个整数Aij表示控制的代价。

接下来N行每行M个整数Bij表示选择的回报。

Output

一个整数,表示最大的回报-代价(如果一个都不控制那么就是0)。

Sample Input

3 3
1 100 100
100 1 100
1 100 100
2 0 0
5 2 0
2 0 0

Sample Output

8

HINT

对于100%的数据,N,M<=50,Aij,Bij都是小于等于100的正整数。

Source

BZOJ 3774: 最优选择( 最小割 )的更多相关文章

  1. BZOJ 3774 最优选择 (最小割+二分图)

    题面传送门 题目大意:给你一个网格图,每个格子都有$a_{ij}$的代价和$b_{ij}$的回报,对于格子$ij$,想获得$b_{ij}$的回报,要么付出$a_{ij}$的代价,要么$ij$周围四联通 ...

  2. [BZOJ 3774] 最优选择 【最小割】

    题目链接:BZOJ - 3774 题目分析 此题与“文理分科”那道题目有些类似.都是使用最小割来求解,先加上可能获得的权值,在减掉必须舍弃的权值(最小割). 文理分科是规定每个人和 S 连就是选文,和 ...

  3. 【BZOJ3774】最优选择 最小割

    [BZOJ3774]最优选择 Description 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择 ...

  4. BZOJ 2039 人员雇佣 二元关系 最小割

    题面太长了,请各位自行品尝—>人员雇佣 分析: 借用题解的描述: a.选择每个人有一个代价Ai b.如果有两个人同时选择就可以获得收益Ei,j c.如果一个人选择另一个不选会产生代价Ei,j 这 ...

  5. BZOJ 1497: [NOI2006]最大获利 最小割

    1497: [NOI2006]最大获利 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1497 Description 新的技术正冲击着手 ...

  6. bzoj 1391 [Ceoi2008]order(最小割)

    [题意] 有n个有偿工作选做,m个机器,完成一个工作需要若干个工序,完成每个工序需要一个机器,对于一个机器,在不同的工序有不同的租费,但买下来的费用只有一个.问最大获益. [思路] 对于工作和机器建点 ...

  7. [BZOJ 3144] [Hnoi2013] 切糕 【最小割】

    题目链接:BZOJ - 3144 题目分析 题意:在 P * Q 的方格上填数字,可以填 [1, R] . 在 (x, y) 上填 z 会有 V[x][y][z] 的代价.限制:相邻两个格子填的数字的 ...

  8. [BZOJ 3894] 文理分科 【最小割】

    题目链接:BZOJ - 3894 题目分析 最小割模型,设定一个点与 S 相连表示选文,与 T 相连表示选理. 那么首先要加上所有可能获得的权值,然后减去最小割,即不能获得的权值. 那么对于每个点,从 ...

  9. bzoj 4873: [Shoi2017]寿司餐厅 [最小割]

    4873: [Shoi2017]寿司餐厅 题意:略 唯一会做的... 一眼最小割 就是最大权闭合子图呀 \(s\rightarrow d_{positive} \rightarrow -d_{negt ...

随机推荐

  1. 利用ItextPdf、core-renderer-R8 来生成PDF

    近期因为工作上的须要,须要做一个简历产品的下载功能,而下载的形式要去为PDF,内容要求为整个简历的内容,并且格式上要求和简历的格式排版时一致的!前期调研.开发,最后測试上线.差点儿相同花了7天的时间. ...

  2. DevExpress.XtraCharts.chartControl

    private Dictionary<string, double> chartPieDataDic = new Dictionary<string, double>(); p ...

  3. gulp简单使用小记

    npm install --save-dev 写入package.json里     var gulp = require('gulp'); var less = require('gulp-less ...

  4. document.body is null

    document.body is null:做前端的同学们对这个错误应该不陌生吧 出现这个问题的原因是:你太着急了,document还没渲染到body呢,你就想调用了,当然会找不到了 解决办法so e ...

  5. UpdatePanel局部刷新用法

    AjaxTest.aspx代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind=&qu ...

  6. Python核心编程读笔 9: 异常

    第10章 异常一.异常1 检测和处理异常 (1)try-except语句 try: try_suite #监控这里的异常 except Exception[, reason]: except_suit ...

  7. Qt 之 show,hide,setVisible,setHidden,close 等小结

    0QObject::deleteLater()delete obj;析构对象1QWidget::setVisible(bool)使得Widget可见或不可见2QWidget::setHidden(bo ...

  8. OC语法3——点语法,self关键字

    点语法:   为了给程序员提供便捷,OC中也引入了点语法.不过它和Java中点语法的意义是完全不同的. 在Java中无论调用任何方法,还是访问public类型的成员变量都是用点语法(.号). 而在OC ...

  9. WebService之Axis2

    写在前面 本文只说Axis2的用法. 1.下载与部署 需要下载两个文件: 下载地址:http://mirrors.cnnic.cn/apache/axis/axis2/java/core/1.7.1/ ...

  10. hdu 2604Queuing dp+ 矩阵快速幂

    题目链接 给一个长度为n的字符串, 每个字符可以使f或m. 问你不包含子串fmf以及fff的字符串数量有多少. 令0表示mm结尾, 1表示mf, 2表示ff, 3表示fm. 那么 f(n+1, 0) ...