BZOJ 2132 圈地计划(最小割)BZOJ 修复工程
Posted 繁凡さん
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2132 圈地计划(最小割)BZOJ 修复工程相关的知识,希望对你有一定的参考价值。
整理的算法模板合集: ACM模板
实际上是一个全新的精炼模板整合计划
题目链接
https://hydro.ac/d/bzoj/p/2132
是 hydro 的 BZOJ 修复工程 !(我也去领了一点题慢慢修着玩,这题就是我修的嘿嘿嘿)
题目描述
最近房地产商 GDOI(Group of Dumbbells Or Idiots) 从 NOI(Nuts Old Idiots) 手中得到了一块开发土地。据了解,这块土地是一块矩形的区域,可以纵横划分为 N × M N×M N×M 块小区域。GDOI 要求将这些区域分为商业区和工业区来开发。根据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值。更具体点,对于第 i i i 行第 j j j 列的区域,建造商业区将得到 A i j A_{ij} Aij 的收益,建造工业区将得到 B i j B_{ij} Bij 的收益。另外不同的区域连在一起可以得到额外的收益,即如果区域 ( i , j ) (i,j) (i,j) 相邻(相邻是指两个格子有公共边)有 K K K 块(显然 K K K 不超过 4 4 4 )类型不同于 ( i , j ) (i,j) (i,j) 的区域,则这块区域能增加 k × C i j k×C_{ij} k×Cij 收益。经过 Tiger.S 教授的勘察,收益矩阵 A , B , C A,B,C A,B,C 都已经知道了。你能帮 GDOI 求出一个收益最大的方案么?
输入格式
输入第一行为两个整数,分别为正整数 N N N 和 M M M ,分别表示区域的行数和列数;
第 2 2 2 到 N + 1 N+1 N+1 列,每行 M M M个整数,表示商业区收益矩阵 A A A ;
第 N + 2 N+2 N+2 到 2 N + 1 2N+1 2N+1 列,每行 M M M 个整数,表示工业区收益矩阵 B B B ;
第 2 N + 2 2N+2 2N+2 到 3 N + 1 3N+1 3N+1行,每行 M M M 个整数,表示相邻额外收益矩阵 C C C 。
输出格式
输出只有一行,包含一个整数,为最大收益值。
输入样例
3 3
1 2 3
4 5 6
7 8 9
9 8 7
6 5 4
3 2 1
1 1 1
1 3 1
1 1 1
输出样例
81
数据范围与约定
N , M ≤ 100 N,M\\leq 100 N,M≤100, 0 ≤ A i , j , B i , j , C i , j ≤ 1 0 3 0\\leq A_{i,j},B_{i,j},C_{i,j}\\leq 10^{3} 0≤Ai,j,Bi,j,Ci,j≤103 。
对于 30 % 30\\% 30% 的数据有 N , M ≤ 6 N, M\\leq 6 N,M≤6;
对于 50 % 50\\% 50% 的数据有 N , M ≤ 20 N, M \\leq 20 N,M≤20;
对于 100 % 100\\% 100% 的数据有 N , M ≤ 100 N,M\\leq 100 N,M≤100。
提示
数据已加强,并重测 – 2015.5.15
Solution
每个点有两种选择,显然考虑最小割模型。
首先考虑最简单的模型一,即每个点仅有 a , b a,b a,b 两种选择收益,没有额外的收益 c c c 。如图一所示,显然我们直接建虚拟源点 S S S 和虚拟汇点 T T T,对于任意一点 1 1 1,向 S S S 连权值为 a [ 1 ] a[1] a[1] 的边,表示选择方案 a a a ,向 T T T 连权值为 b [ 1 ] b[1] b[1] 的边,表示选择方案 b b b,由于每一个点只能有一种选择方案,所以我们只需要割掉一些边,使得 S , T S,T S,T 不连通即可,我们直接求最小割,总边权值减去最小割既是剩余的最大收益。
考虑加上题目中的收益 c c c,题目中的收益 c c c 是相邻点之间方案选择不同才会拥有的附加收益,我们这里先考虑一个简化版问题,即某些给定点对 ( u , v ) (u,v) (u,v)之间方案选择相同才会拥有附加收益,同为 a a a 则获得收益 c a ( u , v ) c_a(u,v) ca(u,v),同为 b b b 则获得收益 c b ( u , v ) c_b(u,v) cb(u,v),也即模型二,P1361 小M的作物 。
我们发现此时需要相同的方案选择,也即对于图一中的两点 1 1 1 和 2 2 2,当且仅当 b [ 1 ] b[1] b[1] 边和 b [ 2 ] b[2] b[2] 边同时割掉之后,也即图二所示,此时可以获得额外收益 c ( 1 , 2 ) c(1,2) c(1,2),割掉两边之后,此时 S , T S,T S,T 不连通,两点选择方案有且仅有一个,符合题意,此时剩余的所有边权是我们获得的收益,我们可以加上额外收益 c ( 1 , 2 ) c(1,2) c(1,2),为了保证当且仅当此时我们才能加上收益 c c c,可以建虚拟源点 x x x, S S S 到 x x x 连权值为 c a ( 1 , 2 ) c_a(1,2) ca(1,2) 的边,此时我们就可以额外获得收益 c a ( 1 , 2 ) c_a(1,2) ca(1,2),为了防止 ( x , 1 ) , ( x , 2 ) (x,1),(x,2) (x,1),(x,2) 被意外割掉不符合题意,我们将其边权设为 I N F INF INF 即可。
综上所述,我们建如图三的模型,总权值减去最小割即为答案。
回到本题的模型三,本题中,每个点相邻的点(上下左右显然最多有 4 4 4 个),选择不同的方案才能获得收益 c c c。
首先处理可以获得收益 c c c 的点集,要求为相邻,显然对图进行黑白染色,即可得到可以获得收益 c c c 的点集方案。此时问题和模型二的差别仅为方案相同和不同。为了将模型三转化为模型二,我们将该条件转变即可,所以就我们可以直接将所有黑色点的收益 a a a 和收益 b b b 交换,不同的条件就直接转化为了相同,问题显然就转化成了模型二,直接建图三跑最小割即可。
Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define num(i, j) ((i - 1) * m + j)
using ll = long long;
const int INF = 1e18, maxn = 5e5 + 7, maxm = 5e6 + 7, maxv = 2e3 + 7;
int ans;
int head[maxn], nex[maxm], ver[maxm], tot;
ll edge[maxm];
int n, m, s, t, n_cnt;
ll maxflow;
ll deep[maxn];
int now[maxm];
queue <int> q;
int a[maxv][maxv], b[maxv][maxv], c[maxv][maxv];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
inline void add(int x,int y,int z){
ver[tot] = y; edge[tot] = z; nex[tot] = head[x]; head[x] = tot ++ ;
ver[tot] = x; edge[tot] = 0; nex[tot] = head[y]; head[y] = tot ++ ;
}
inline bool bfs() {
for(int i = 0; i <= n_cnt; ++ i)
deep[i] = INF, now[i] = head[i];
while(!q.empty())
q.pop();
q.push(s);
deep[s] = 0;
while(!q.empty()){
int x = q.front();
q.pop();
for(int i = head[x]; ~i; i = nex[i]){
int y = ver[i];
if(edge[i] > 0 && deep[y] ==以上是关于BZOJ 2132 圈地计划(最小割)BZOJ 修复工程的主要内容,如果未能解决你的问题,请参考以下文章