整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


题目链接

https://hydro.ac/d/bzoj/p/2132

是 hydro 的 BZOJ 修复工程 !(我也去领了一点题慢慢修着玩,这题就是我修的嘿嘿嘿)

题目描述

最近房地产商 GDOI(Group of Dumbbells Or Idiots) 从 NOI(Nuts Old Idiots) 手中得到了一块开发土地。据了解,这块土地是一块矩形的区域,可以纵横划分为 N×MN×MN×M 块小区域。GDOI 要求将这些区域分为商业区和工业区来开发。根据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值。更具体点,对于第 iii 行第 jjj 列的区域,建造商业区将得到 AijA_{ij}Aij​ 的收益,建造工业区将得到 BijB_{ij}Bij​ 的收益。另外不同的区域连在一起可以得到额外的收益,即如果区域 (i,j)(i,j)(i,j) 相邻(相邻是指两个格子有公共边)有 KKK 块(显然 KKK 不超过 444 )类型不同于 (i,j)(i,j)(i,j) 的区域,则这块区域能增加 k×Cijk×C_{ij}k×Cij​ 收益。经过 Tiger.S 教授的勘察,收益矩阵 A,B,CA,B,CA,B,C 都已经知道了。你能帮 GDOI 求出一个收益最大的方案么?

输入格式

输入第一行为两个整数,分别为正整数 NNN 和 MMM ,分别表示区域的行数和列数;

第 222 到 N+1N+1N+1 列,每行 MMM个整数,表示商业区收益矩阵 AAA ;

第 N+2N+2N+2 到 2N+12N+12N+1 列,每行 MMM 个整数,表示工业区收益矩阵 BBB ;

第 2N+22N+22N+2 到 3N+13N+13N+1行,每行 MMM 个整数,表示相邻额外收益矩阵 CCC 。

输出格式

输出只有一行,包含一个整数,为最大收益值。

输入样例

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≤100N,M\leq 100N,M≤100,0≤Ai,j,Bi,j,Ci,j≤1030\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≤6N, M\leq 6N,M≤6;

对于 50%50\%50% 的数据有 N,M≤20N, M \leq 20N,M≤20;

对于 100%100\%100% 的数据有 N,M≤100N,M\leq 100N,M≤100。

提示

数据已加强,并重测 – 2015.5.15

Solution

每个点有两种选择,显然考虑最小割模型。

首先考虑最简单的模型一,即每个点仅有 a,ba,ba,b 两种选择收益,没有额外的收益 ccc 。如图一所示,显然我们直接建虚拟源点 SSS 和虚拟汇点 TTT,对于任意一点 111,向 SSS 连权值为 a[1]a[1]a[1] 的边,表示选择方案 aaa ,向 TTT 连权值为 b[1]b[1]b[1] 的边,表示选择方案 bbb,由于每一个点只能有一种选择方案,所以我们只需要割掉一些边,使得 S,TS,TS,T 不连通即可,我们直接求最小割,总边权值减去最小割既是剩余的最大收益。

图一

考虑加上题目中的收益 ccc,题目中的收益 ccc 是相邻点之间方案选择不同才会拥有的附加收益,我们这里先考虑一个简化版问题,即某些给定点对 (u,v)(u,v)(u,v)之间方案选择相同才会拥有附加收益,同为 aaa 则获得收益 ca(u,v)c_a(u,v)ca​(u,v),同为 bbb 则获得收益 cb(u,v)c_b(u,v)cb​(u,v),也即模型二,P1361 小M的作物 。

我们发现此时需要相同的方案选择,也即对于图一中的两点 111 和 222,当且仅当 b[1]b[1]b[1] 边和 b[2]b[2]b[2] 边同时割掉之后,也即图二所示,此时可以获得额外收益 c(1,2)c(1,2)c(1,2),割掉两边之后,此时 S,TS,TS,T 不连通,两点选择方案有且仅有一个,符合题意,此时剩余的所有边权是我们获得的收益,我们可以加上额外收益 c(1,2)c(1,2)c(1,2),为了保证当且仅当此时我们才能加上收益 ccc,可以建虚拟源点 xxx,SSS 到 xxx 连权值为 ca(1,2)c_a(1,2)ca​(1,2) 的边,此时我们就可以额外获得收益 ca(1,2)c_a(1,2)ca​(1,2),为了防止 (x,1),(x,2)(x,1),(x,2)(x,1),(x,2) 被意外割掉不符合题意,我们将其边权设为 INFINFINF 即可。

图二

综上所述,我们建如图三的模型,总权值减去最小割即为答案。

图三

回到本题的模型三,本题中,每个点相邻的点(上下左右显然最多有 444 个),选择不同的方案才能获得收益 ccc。

首先处理可以获得收益 ccc 的点集,要求为相邻,显然对图进行黑白染色,即可得到可以获得收益 ccc 的点集方案。此时问题和模型二的差别仅为方案相同和不同。为了将模型三转化为模型二,我们将该条件转变即可,所以就我们可以直接将所有黑色点的收益 aaa 和收益 bbb 交换,不同的条件就直接转化为了相同,问题显然就转化成了模型二,直接建图三跑最小割即可。

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] == INF){ q.push(y);deep[y] = deep[x] + 1;if(y == t)return 1; }}}return 0;
}ll dfs(int x, ll flow) {if(x == t)return flow;ll ans = 0, k, i; for(i = now[x]; ~i && flow; i = nex[i]){now[x] = i; int y = ver[i];if(edge[i] > 0 && (deep[y] == deep[x] + 1)){  k = dfs(y,min(flow,edge[i])); if(!k)deep[y] = INF; edge[i] -= k; edge[i ^ 1] += k; ans += k;flow -= k;} } return ans;
}void dinic() {while(bfs())maxflow += dfs(s,INF);
}signed main()
{memset(head, -1, sizeof head);maxflow = 0;ans = 0;scanf("%lld%lld", &n, &m);n_cnt = n * m;s = ++ n_cnt, t = ++ n_cnt;for (int i = 1; i <= n; ++ i) {for (int j = 1; j <= m; ++ j) {scanf("%lld", &a[i][j]);ans += a[i][j];}}for (int i = 1; i <= n; ++ i) {for (int j = 1; j <= m; ++ j) {scanf("%lld", &b[i][j]);ans += b[i][j];}}for (int i = 1; i <= n; ++ i) {for (int j = 1; j <= m; ++ j) {scanf("%lld", &c[i][j]);}}for (int i = 1; i <= n; ++ i)for (int j = 1; j <= m; ++ j)if((i + j) & 1)swap(a[i][j], b[i][j]);for (int i = 1; i <= n; ++ i) {for (int j = 1; j <= m; ++ j) {add(s, num(i, j), a[i][j]);add(num(i, j), t, b[i][j]);}}for (int i = 1; i <= n; ++ i) {for (int j = 1; j <= m; ++ j) {for (int k = 0; k < 4; ++ k) {int nx = i + dx[k];int ny = j + dy[k];if(nx <= 0 || nx > n || ny <= 0 || ny > m) continue;int x = ++ n_cnt;int y = ++ n_cnt;ans += 2 * c[i][j];add(s, x, c[i][j]);add(x, num(i, j), INF);add(x, num(nx, ny), INF);add(num(i, j), y, INF);add(num(nx, ny), y, INF);add(y, t, c[i][j]);}}}dinic(); ans -= maxflow;cout << ans << endl;return 0;
}

BZOJ 2132 圈地计划(最小割)【BZOJ 修复工程】相关推荐

  1. [国家集训队]happiness 最小割 BZOJ 2127

    题目描述 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文 ...

  2. BZOJ 4657: tower【路径最小割约束】

    题面: Description Nick最近在玩一款很好玩的游戏,游戏规则是这样的: 有一个n*m的地图,地图上的每一个位置要么是空地,要么是炮塔,要么是一些BETA狗,Nick需 要操纵炮塔攻击BE ...

  3. BZOJ.3218.a + b Problem(最小割ISAP 可持久化线段树优化建图)

    BZOJ UOJ 首先不考虑奇怪方格的限制,就是类似最大权闭合子图一样建图. 对于奇怪方格的影响,显然可以建一条边\((i\to x,p_i)\),然后由\(x\)向\(1\sim i-1\)中权值在 ...

  4. [BZOJ 3894]文理分科(最小割)

    Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同 ...

  5. bzoj 3232: 圈地游戏【分数规划+最小割】

    数组开小导致TTTTTLE-- 是分数规划,设sm为所有格子价值和,二分出mid之后,用最小割来判断,也就是判断sm-dinic()>=0 这个最小割比较像最大权闭合子图,建图是s像所有点连流量 ...

  6. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  7. BZOJ 4823 Luogu P3756 [CQOI2017]老C的方块 (网络流、最小割)

    题目链接 (Luogu) https://www.luogu.org/problem/P3756 (BZOJ) http://lydsy.com/JudgeOnline/problem.php?id= ...

  8. BZOJ 3894 Luogu P4313 文理分科 (最小割)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3894 (luogu) https://www.luogu.org/pro ...

  9. BZOJ 3218 UOJ #77 A+B Problem (主席树、最小割)

    BZOJ 3218 UOJ #77 A+B Problem (主席树.最小割) 大名鼎鼎的A+B Problem, 主席树优化最小割-- 调题死活调不对,一怒之下改了一种写法交上去A了,但是改写法之后 ...

最新文章

  1. 有没有一只蜻蜓永远为你守候?
  2. 【机器学习PAI实战】—— 玩转人工智能之综述
  3. 对 VR 项目开发流程的调研
  4. 当Windows Vista提示“内存不足”……
  5. Mysql临时表的用法 - 51CTO.COM
  6. python编程注释_自学python编程笔记之:python的注释
  7. 单片机c语言随机数,单片机C语言如何产生随机数
  8. unity游戏中提示信息如何实现_Unity编辑器操作面试题集锦(上)
  9. 1.UNIX网络编程卷1:源码配置
  10. Windows Phone 8安装包中的文件和独立存储区中的文件访问
  11. LeetCode-116. 填充每个节点的下一个右侧节点指针
  12. X-NUCA全国高校网安联赛7月训练题解
  13. window.location.href跳转无效 IE Bug【转载】
  14. C:矩形相交、相包含、相离关系判断
  15. 中国高性能计算服务器排名,2007中国高性能计算100强出炉
  16. android百度地图3d路线,百度地图Android V2.0新增卫星图及3D模式功能
  17. 蛋蛋读NVMe之一:为什么刘备需要NVMe
  18. 最小二乘(OLS)回归法及其在R中的…
  19. JS基础 day1 | JS介绍、变量常量、数据类型及转换
  20. 笔记本升级--固态硬盘安装双系统win10-CentOS

热门文章

  1. 图像色彩空间与应用转换
  2. 基于OpenCV的实时睡意检测系统
  3. 编写更少量的代码:使用apache commons工具类库
  4. 异步获取邮件推送结果
  5. Tomcat6 内存和线程配置
  6. [笔记].关于在Quartus II 11.0无法正常使用SignalTap的解决方法
  7. 对大龄程序员的五大误解
  8. 刷新aspx页面的六种方法
  9. .Net并行库介绍——Task(1)
  10. hi3516中home中的ko