[BZOJ 3894] 文理分科 【最小割】
题目链接:BZOJ - 3894
题目分析
最小割模型,设定一个点与 S 相连表示选文,与 T 相连表示选理。
那么首先要加上所有可能获得的权值,然后减去最小割,即不能获得的权值。
那么对于每个点,从 S 向它连权值为它选文的价值的边,从它向 T 连权值为它选理的价值的边。
对于一个点,它和与它相邻的点构成了一个集合,这个集合如果都选文,可以获得一个价值v1,如果都选理,可以获得一个价值 v2。
只要这个集合中有一个点选文,就无法获得 v2,只要有一个点选理,就无法获得 v1。
那么处理方式就是,新开一个点,从它向 T 连 v2 的边,从这个集合中的每个点向它连 INF 边。这样,只要集合中有一个点选文,就必须割掉 v2。
v1的处理同理。
代码
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; const int MaxN = 100 + 5, MaxNode = 30000 + 15, Dx[5] = {0, 0, 1, -1}, Dy[5] = {1, -1, 0, 0}, INF = 999999999; int n, m, S, T, Tot, Sum, MaxFlow;
int Idx[MaxN][MaxN], Wk[MaxN][MaxN][3], Lk[MaxN][MaxN][3], Num[MaxNode], d[MaxNode]; struct Edge
{
int v, w;
Edge *Next, *Other;
} E[MaxNode * 16], *P = E, *Point[MaxNode], *Last[MaxNode]; inline void AddEdge(int x, int y, int z)
{
Edge *Q = ++P; ++P;
P -> v = y; P -> w = z;
P -> Next = Point[x]; Point[x] = P; P -> Other = Q;
Q -> v = x; Q -> w = 0;
Q -> Next = Point[y]; Point[y] = Q; Q -> Other = P;
} inline int gmin(int a, int b) {return a < b ? a : b;} int DFS(int Now, int Flow)
{
if (Now == T) return Flow;
int ret = 0;
for (Edge *j = Last[Now]; j; j = j -> Next)
if (j -> w && d[Now] == d[j -> v] + 1)
{
Last[Now] = j;
int p = DFS(j -> v, gmin(j -> w, Flow - ret));
ret += p; j -> w -= p; j -> Other -> w += p;
if (ret == Flow) return ret;
}
if (d[S] >= Tot) return ret;
if (--Num[d[Now]] == 0) d[S] = Tot;
++Num[++d[Now]];
Last[Now] = Point[Now];
return ret;
} inline bool Inside(int x, int y)
{
if (x < 1 || x > n) return false;
if (y < 1 || y > m) return false;
return true;
} int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
Idx[i][j] = (i - 1) * m + j;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d", &Wk[i][j][0]);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d", &Lk[i][j][0]);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d", &Wk[i][j][1]);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d", &Lk[i][j][1]);
Tot = n * m * 3; S = ++Tot; T = ++Tot;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
{
Sum += Wk[i][j][0] + Wk[i][j][1];
Sum += Lk[i][j][0] + Lk[i][j][1];
AddEdge(S, Idx[i][j], Wk[i][j][0]);
AddEdge(Idx[i][j], T, Lk[i][j][0]);
int x, y;
for (int k = 0; k < 4; ++k)
{
x = i + Dx[k]; y = j + Dy[k];
if (!Inside(x, y)) continue;
AddEdge(Idx[x][y], n * m + Idx[i][j], INF);
AddEdge(n * m * 2 + Idx[i][j], Idx[x][y], INF);
}
AddEdge(Idx[i][j], n * m + Idx[i][j], INF);
AddEdge(n * m * 2 + Idx[i][j], Idx[i][j], INF);
AddEdge(n * m + Idx[i][j], T, Lk[i][j][1]);
AddEdge(S, n * m * 2 + Idx[i][j], Wk[i][j][1]);
}
MaxFlow = 0;
memset(d, 0, sizeof(d));
memset(Num, 0, sizeof(Num)); Num[0] = Tot;
for (int i = 1; i <= Tot; ++i) Last[i] = Point[i];
while (d[S] < Tot) MaxFlow += DFS(S, INF);
printf("%d\n", Sum - MaxFlow);
return 0;
}
[BZOJ 3894] 文理分科 【最小割】的更多相关文章
- BZOJ 3894: 文理分科 [最小割]
3894: 文理分科 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 674 Solved: 392[Submit][Status][Discuss] ...
- BZOJ 3894 Luogu P4313 文理分科 (最小割)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3894 (luogu) https://www.luogu.org/pro ...
- bzoj 3894: 文理分科
Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位. ...
- BZOJ3894文理分科——最小割
题目描述 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同学必须从 ...
- P4313 文理分科 最小割
$ \color{#0066ff}{ 题目描述 }$ 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行描述,每个格 ...
- ●BZOJ 3894 文理分科
题链: https://vijos.org/d/ljt12138/p/58c696b8d3d8a16c62a248d4 (要权限号啊...用这个交吧) 题解: 题目大意: N*M的矩阵,每个位置 ...
- 【BZOJ3894】【Luogu3358】文理分科 - 最小割多选一模型
链接Click Here 这个题就是个板子的最小割多选一模型啦\(QwQ\),这里介绍一种通用的解法. 抛开组合收益不谈,这个题就是一个简单的最小割模型.我们只需要建出来这样一张图,在上面跑最小割,割 ...
- 【BZOJ3894】文理分科 最小割
[BZOJ3894]文理分科 Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行描述,每个格 ...
- bzoj 3894 文理分科【最小割+dinic】
谁说这道和2127是双倍经验的来着完全不一样啊? 数组开小会TLE!数组开小会TLE!数组开小会TLE! 首先sum统计所有收益 对于当前点\( (i,j) \)考虑,设\( x=(i-1)*m+j ...
随机推荐
- 数据结构与算法/leetcode/lintcode题解
http://algorithm.yuanbin.me/zh-hans/index.html
- careercup-数组和字符串1.2
1.2 用C或C++实现void reverse(char *str)函数,即反转一个null结尾的字符串. C++实现代码: #include<iostream> #include< ...
- codeblocks创建和使用静态库(C语言)
静态库 (扩展名为 .a 或 .lib) 是包含函数的文件,用于在link阶段整合执行程序,动态链接库(扩展名 .dll)是不在link阶段整合进执行程序中的. DLL文件在执行阶段动态调用 下面 ...
- javascript技巧字典【转藏】
2015-12-31 js判断undefined类型 if (reValue== undefined){ alert("undefined"); } 发现判断不出来, ...
- A的ascll吗是多少?
//输入一个字符,返回他的ascll码 #include<stdio.h> int main() { char a; while(scanf("%c",&a)! ...
- SVN服务器的搭建 分类: 网络 2014-11-27 01:18 204人阅读 评论(4) 收藏
一.首先来下载和安装SVN服务器 现在Subversion已经迁移到apache网站上了,下载地址: http://subversion.apache.org/packages.html 这是二进制文 ...
- .Net开源SqlServer ORM框架SqlSugar整理
一.链接整理 官方Git源代码地址: https://github.com/sunkaixuan/SqlSugar 最新发布版更新地址:当前版本Release 3.5.2.1 https://gith ...
- 关于jQuery,$(":button") 中的冒号是什么意思?
$(":button") 表示匹配所有的按钮.$("input:checked")表示匹配所有选中的被选中元素(复选框.单选框等,不包括select中的opti ...
- mac管理员密码破解
方法一:官方解决方法.找出电脑原配的系统盘,找不到就借一张或者刻录一张,重启电脑,启动的时候按C键,选好语言后进入安装的时候,点击“常用工具”,里面有一项是“重设密码”,这时就可以重新设定Mac OS ...
- swift 遍历
最简单的一个遍历数组 for 随便起个名字 in 升级 上面的看不懂的话,这个应该会简单点 import UIKit let interestingNumbers = [ ,,,,,], ,,,,,] ...