[题解] bzoj3894 文理分科

技术[题解] bzoj3894 文理分科 [题解] bzoj3894 文理分科题目链接
题目描述
\(n\) 行 \(m\) 列的矩阵,每个人可以选文科或者理科。第 \(i,j\) 个人选文科贡献为 \

[题解] bzoj3894文理分科

题目链接

题目描述

\(n\)行\(m\)列的矩阵,每个人可以选文科或者理科。第\(i,j\)个人选文科贡献为\(a_{i,j}\),选理科贡献为\(b_{i,j}\),周围及自己选文科贡献为\(c_{i,j}\),周围及自己选理科贡献为\(d_{i,j}\)。

思路

建图方法见代码。

利用最大权闭合子图,考虑全选文科,初始值为\(\sum a_{i,j} c_{i,j}\)。

那么理科的贡献就为\(b_{i,j}\),全选理科的贡献为\(d_{i,j}\)。

不选文科的贡献为\(-a_{i,j}\),\(5\)人之中有一个不选的贡献为\(-c_{i,j}\)。

则内部构图中,有三个约束条件:

选了理科,则必不选文科。

选了\(d_{i,j}\),则四周及自己都必须选理科。

选了一个不选文科,则与这个点相关的\(c_{i,j}\)都必须破坏,及必选相关的\(-c_{i,j}\)。

则答案为\(\ sum a _ { I,j} b_{i,j} c_{i,j} d_{i,j})-mincut\)。

Code

#包含cstdio

#定义INF0x3f3f

const int MAXN=2e5 5

const int MaxM=1e 6 5;

结构边缘{ int To,Cap,Next}边[MAXM 1];

int head[MAXN],tot=1;

void Addedge(int u,int v,int w){ 0

边缘[ tot].下一个=头[u],边[tot]。To=v,edge[tot].Cap=w,head[u]=tot;

边缘[ tot].下一个=头部[v],边缘[tot].To=u,edge[tot].Cap=0,head[v]=tot;

}

int cur[MAXN],dep[MAXN],que[MAXN],qhead,qtail

int n,m,s,t;

int addx[]={0,0,1,-1,0 };

int addy[]={1,-1,0,0,0 };

int ans

int Min(int x,int y){ return x y x :y;}

布尔bfs(布尔限制){ 0

for(int I=s;I=t;i ) dep[i]=0,cur[I]=head[I];

qhead=1;qtail=1;que[1]=t;dep[t]=1;

while(qhead=qtail){ 0

int u=que[qhead];

for(int I=head[u];我;i=edge[i].下一个){ 0

int v=edge[i].到;

if(!副[v]边[i ^ 1].Cap(!限制||!(一(1)))(

dep[v]=dep[u]1;

que[qtail]=v;

if (v==s)返回1;

}

}

}

返回0;

}

int dfs(int u,int flow){ 0

if(u==t ||!流量)回流;

int rest=flow

for(int I=cur[u];我休息;i=edge[i].下一个){ 0

cur[u]=I;

int v=edge[i].到;

if(dep[v]==dep[u] - 1边[i].Cap) {

int del=dfs(v,Min(静止,边缘[i]).cap));

rest-=del;边缘cap-=del;边缘[我^ 1]。Cap=del

if(!del)dep[v]=-2;

}

}

回流休息;

}

int Dinic(){ 0

int res=0,流;

while (bfs(1)) while ((flow=dfs(s,INF)))RES=flow;

while (bfs(0)) while ((flow=dfs(s,INF)))RES=flow;

返回表示留数

}

int Get(int x,int y,int h){ 0

return(x-1)* m y n * m * h;

}

int main(){ 0

scanf('%d %d ',n,m);

s=0,t=4 * n * m ^ 1;

for(int I=1;I=n;I){ 0

for (int j=1,a;j=m;j ) {

scanf("% d ",a);

Addedge(Get(i,j,0),t,a);

ans=a;

}

}

for(int I=1;I=n;I){ 0

for (int j=1,a;j=m;j ) {

scanf("% d ",a);

Addedge(s,Get(i,j,1),a);

Addedge(Get(i,j,1),Get(i,j,0),INF);

ans=a;

}

}

for(int I=1;I=n;I){ 0

for (int j=1,a;j=m;j ) {

scanf("% d ",a);

Addedge(Get(i,j,2),t,a);

ans=a;

for(int k=0;K5;k){ 0

int ni=I addx[k];

int NJ=j addy[k];

if (ni 1 || ni n || nj 1 || nj m)继续;

Addedge(Get(ni,nj,0),Get(i,j,2),INF);

}

}

}

for(int I=1;I=n;I){ 0

for (int j=1,a;j=m;j ) {

scanf("% d ",a);

ans=a;

Addedge(s,Get(i,j,3),a);

for(int k=0;K5;k){ 0

int ni=I addx[k];

int NJ=j addy[k];

if (ni 1 || ni n || nj 1 || nj m)继续;

Addedge(Get(i,j,3),Get(ni,nj,1),INF);

}

}

}

printf('%d ',ans-Dinic());

返回0;

}

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/141448.html

(0)

相关推荐

  • python中如何操作使用列表

    技术python中如何操作使用列表这篇文章给大家分享的是有关python中如何操作使用列表的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。# 列表的基本操作
    # 赋值、删除列表元素、分片赋值#

    攻略 2021年11月24日
  • 使用sqlite数据要获取什么实例(sqlite怎么添加表的内容)

    技术SQLite中的FROM子句怎么用这篇文章主要介绍SQLite中的FROM子句怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!SQLite中的FROM子句FROM子句从数据库中可以获取到一

    攻略 2021年12月18日
  • win10组策略怎么打开,win10组策略打不开怎么办

    技术win10组策略怎么打开,win10组策略打不开怎么办1、打开电脑win10组策略怎么打开,在win10系统桌面上的空白处鼠标右键点击新建,然后点击新建文本文档选项;2、之后电脑桌面就会显示新建文本文档,然后双击打开

    生活 2021年10月30日
  • RHEL7的基本命令有哪些呢

    技术RHEL7的基本命令有哪些呢今天就跟大家聊聊有关RHEL7的基本命令有哪些呢,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。本节单词整理:Termnial :

    攻略 2021年11月11日
  • c++ 文本处理

    技术c++ 文本处理 c++ 文本处理c++ 文本处理
    1、使用sstream版本
    (1)功能:截取第一列为1以后的数据,如下图,截取第5行(包括第5行)以后的数据,前面4行数据丢弃。(2)代码:tex

    礼包 2021年12月3日
  • 有哪些强大的静态代码分析工具

    技术有哪些强大的静态代码分析工具本篇内容介绍了“有哪些强大的静态代码分析工具”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成

    攻略 2021年10月22日