题目链接: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] 文理分科 【最小割】的更多相关文章

  1. BZOJ 3894: 文理分科 [最小割]

    3894: 文理分科 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 674  Solved: 392[Submit][Status][Discuss] ...

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

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

  3. bzoj 3894: 文理分科

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

  4. BZOJ3894文理分科——最小割

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

  5. P4313 文理分科 最小割

    $ \color{#0066ff}{ 题目描述 }$ 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行描述,每个格 ...

  6. ●BZOJ 3894 文理分科

    题链: https://vijos.org/d/ljt12138/p/58c696b8d3d8a16c62a248d4 (要权限号啊...用这个交吧) 题解: 题目大意:    N*M的矩阵,每个位置 ...

  7. 【BZOJ3894】【Luogu3358】文理分科 - 最小割多选一模型

    链接Click Here 这个题就是个板子的最小割多选一模型啦\(QwQ\),这里介绍一种通用的解法. 抛开组合收益不谈,这个题就是一个简单的最小割模型.我们只需要建出来这样一张图,在上面跑最小割,割 ...

  8. 【BZOJ3894】文理分科 最小割

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

  9. bzoj 3894 文理分科【最小割+dinic】

    谁说这道和2127是双倍经验的来着完全不一样啊? 数组开小会TLE!数组开小会TLE!数组开小会TLE! 首先sum统计所有收益 对于当前点\( (i,j) \)考虑,设\( x=(i-1)*m+j ...

随机推荐

  1. python如何使用 os.path.exists()--Learning from stackoverflow 分类: python 2015-04-23 20:48 139人阅读 评论(0) 收藏

    Q&A参考连接 Problem:IOError: [Errno 2] No such file or directory. os.path.exists() 如果目录不存在,会返回一个0值. ...

  2. Cocos2d-x 3.1.1 学习日志9--一“上一下其乐无穷”游戏开发系列一

    下载地址:http://app.mi.com/search?keywords=%E4%B8%80%E4%B8%8A%E4%B8%80%E4%B8%8B%E5%85%B6%E4%B9%90%E6%97% ...

  3. python learning_curve函数

    这个函数需要引用sklearn包 import sklearn from sklearn.learning_curve import learning_curve 这个函数的调用格式是: learni ...

  4. H TML5 之 (4) 小项目一 时钟

    这里做一个HTML5 入门的练手,一个小时钟项目,可以再上面拓展很多,程序员培养的就是思想 <!DOCTYPE HTML> <html> <head> <ti ...

  5. bootstap 滚动监听

    ---首先结合源代码介绍官网的说明 ---然后总结了使用滚动监听的几个步骤 ---最后给出一个简单的例子 ---关键的一点:整体有点零散和乱七八糟,辛苦你的思维和眼睛了,呵呵 ------------ ...

  6. js EasyUI前台 全选的实现

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAWcAAAEQCAIAAADj/SKjAAAgAElEQVR4nO1dz48ry1W+/5N3swaFEP ...

  7. [Twisted] Protocols协议和Protocol Factories 协议工厂

    Protocols 描述了如何异步处理网络事件.Twisted维护了许多协议的实现,如HTTP,Telent,DNS,IMAP.Portocols实现了IProtocol接口, IProtocol包含 ...

  8. Win32中GDI+应用(五)--GDI与GDI+编程模型的区别

    在GDI里面,你要想开始自己的绘图工作,必须先获取一个device context handle,然后把这个handle作为绘图复方法的一个参数,才能完成任务.同时,device context ha ...

  9. YouTube视频代码总结

    var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api" ...

  10. DOM中的范围 createRange()

    学习<JavaScript 高级程序设计> 12章dom范围的笔记 dom2级在Document类型中定义了 createRange()方法: 创建range对象很简单 var range ...