题目链接: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. oracle用户管理实例

    oracle中的用户角色分为预定义角色和自定义角色. 角色是把常用的权限集中起来形成角色. 授权/分配角色命令 grant 权限/角色 to 用户 收回权限命令: revoke 综合案例: 创建一个用 ...

  2. 项目打包 tomcat部署

    IDE: IDEA 1.项目maven管理先执行 clean,再执行 compile 2.如果编译compile不成功,则将 C:\Users\Administrator\.m2\repository ...

  3. microchip PIC芯片使用方法

    pickit3调试器使用: http://www.eeboard.com/evaluation/pickit3debug/1/ MPLAB环境使用: 1.代码折叠功能 2.代码补全功能 3.函数跳转功 ...

  4. (转)Spring读书笔记-----Spring核心机制:依赖注入

    Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的.因此,我们说这些对象间存在依赖关系.加入A组件调用了B组件的方法,我们就 ...

  5. web 自定义监听器中设置加载系统相关的静态变量及属性

    直接上代码: 在src下新建一个StartListener 实现接口ServletContextListener,: /** * @Title:StartListener.java * @Packag ...

  6. android中ListView控件

    今天学习了ListView控件和页面跳转,下面大致介绍下: 第一步:创建显示内容的文件vlist.xml: <?xml version="1.0" encoding=&quo ...

  7. 一个自定义线程池的小Demo

    在项目中如果是web请求时候,IIS会自动分配一个线程来进行处理,如果很多个应用程序共享公用一个IIS的时候,线程分配可能会出现一个问题(当然也是我的需求造成的) 之前在做项目的时候,有一个需求,就是 ...

  8. .NET多线程同步方法详解

    .NET多线程同步方法详解(一):自由锁(InterLocked) .NET多线程同步方法详解(二):互斥锁(lock) NET多线程同步方法详解(三):读写锁(ReadWriteLock) .NET ...

  9. 组策略彻底解决windows 2003 终端数

         win2003的话可以从组策略修改: 组策略级别要高于终端服务配置,当启用组策略后终端服务配置中的相应选项会变成灰色不可修改 运行-gpedit.msc-计算机配置-管理模板-Windows ...

  10. 淘宝链接中的spm参数

    什么是SPM SPM是淘宝社区电商业务(xTao)为外部合作伙伴(外站)提供的一套跟踪引导成交效果数据的解决方案. 下面是一个跟踪点击到宝贝详情页的引导成交效果数据的SPM示例: http://det ...