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

某个点(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. ASP.NET MVC 中将FormCollection与实体间转换方法【转】

    将Action动作中传递的FormCollection转变成对应的实体,可以使用Controller的TryUpdateModel()方法. 示例如下: [HttpPost] public Actio ...

  2. 高效搭建Spark全然分布式集群

    写在前面一: 本文具体总结Spark分布式集群的安装步骤,帮助想要学习Spark的技术爱好者高速搭建Spark的学习研究环境. 写在前面二: 使用软件说明 约定,Spark相关软件存放文件夹:/usr ...

  3. EBS R12 修改 apps 密码[Z]

    注意:修改密码时应保证所有用户已退出, 最好是关闭应用实例.不用关闭数据库.在修改密码之前一定要改备下数据库中的FND_ORACLE_USERID和FND_USER表.FNDCPASS工具会自动把AP ...

  4. NSThread 的用法

    一.线程的注意点: 1.不要同时开太多的线程(最多不要超过5条,其中包括主线程) 2.线程概念 2.1.主线程:UI 线程,显示.刷新 UI 界面,处理 UI 控件的事件 2.2.子线程:后台线程,异 ...

  5. 20160121--Spring

    package com.hanqi; public class HelloWorld { public HelloWorld() { } public HelloWorld(String name) ...

  6. ecmall 点滴记录

    /* 取得列表数据 */ $model_wish =& m('wish'); $wish= $model_wish->find(array( 'conditions' => 'us ...

  7. C语言中头文件<stdio.h>中的#ifndef _STDIO_H_

    先了解这里的相关知识:http://www.cnblogs.com/stemon/p/4000468.html 头文件的中的#ifndef,这是一个很关键的东西.比如你有两个C文件,这两个C文件都in ...

  8. JVM学习之实例分析JVM安全体系

    转自:http://www.importnew.com/17093.html,感谢分享 类加载器的作用就是将真实的class文件根据位置将该Java类的字节码装入内存,并生成对应的Class对象.用户 ...

  9. onload ready

    确保在 <body> 元素的onload事件中没有注册函数,否则不会触发$(document).ready()事件. 可以在同一个页面中无限次地使用$(document).ready()事 ...

  10. 工作备份 build.gradle

    apply plugin: 'com.android.application' android { compileSdkVersion 22 buildToolsVersion '22.0.0' de ...