题目大意:给出一个 n∗mn*mn∗m 的矩阵,每个格子都有两个权值 aaa 和 bbb,分别代表花费和收益。一个格子被占,当且仅当:

  1. 格子上有人
  2. 格子的上下左右都有人

格子被占可以获得收益 bbb,格子上有人需要花费 aaa,问如何分配可以使得收益最高。

题目分析:很经典,但我不会的一个模型。

拆点最小割,首先棋盘问题不难想到奇偶拆点,在此基础上将每个点再拆一下用来维护 bbb,再加点无穷大的边用来调和 aaa:

上图中 x1x_1x1​ 和 x2x_2x2​ 是奇数点的入点和出点, y1y_1y1​ 和 y2y_2y2​ 是偶数点的入点和出点。

那么此时最小割就只有三种情况:

  1. 割掉 st−x1st-x_1st−x1​:选择点 xxx
  2. 割掉 y2−edy_2-edy2​−ed:选择点 yyy
  3. 割掉 x1−x2x_1-x_2x1​−x2​ 和 y1−y2y_1-y_2y1​−y2​:两个点都不选

不难看出,上述三种情况实质上对应着本题的两个条件,也就是对于某个点,获得 bbb 时的两种情况:

  1. 割掉某个点本身的 aaa
  2. 割掉某个点四周的 aaa

所以最后用 ∑b\sum b∑b 减去最小割就是最大的答案了。

代码:

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) (x&-x)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f;
}
template<typename T>
inline void write(T x)
{if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=4100;
template<typename T>
struct Dinic
{const static int N=4100;const static int M=N*N;const T inf=0x3f3f3f3f3f3f3f3f;struct Edge{int to,next;T w;}edge[M];//边数int head[N],cnt;void addedge(int u,int v,T w){edge[cnt].to=v;edge[cnt].w=w;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].to=u;edge[cnt].w=0;//反向边边权设置为0edge[cnt].next=head[v];head[v]=cnt++;}int d[N],now[N];//深度 当前弧优化bool bfs(int s,int t)//寻找增广路{memset(d,0,sizeof(d));queue<int>q;q.push(s);now[s]=head[s];d[s]=1;while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;T w=edge[i].w;if(d[v])continue;if(!w)continue;d[v]=d[u]+1;now[v]=head[v];q.push(v);if(v==t)return true;}}return false;}T dinic(int x,int t,T flow)//更新答案{if(x==t)return flow;T rest=flow,i;for(i=now[x];i!=-1&&rest;i=edge[i].next){int v=edge[i].to;T w=edge[i].w;if(w&&d[v]==d[x]+1){T k=dinic(v,t,min(rest,w));if(!k)d[v]=0;edge[i].w-=k;edge[i^1].w+=k;rest-=k;}}now[x]=i;return flow-rest;}void init(){memset(now,0,sizeof(now));memset(head,-1,sizeof(head));cnt=0;}T solve(int st,int ed){T ans=0,flow;while(bfs(st,ed))while(flow=dinic(st,ed,inf))ans+=flow;return ans;}
};
Dinic<int>t;
const int b[4][2]={0,1,0,-1,1,0,-1,0};
int id[50][50][2],tot;
int main()
{#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);t.init();int n,m,st=N-1,ed=st-1,sum=0;read(n),read(m);for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {for(int k=0;k<2;k++) {id[i][j][k]=++tot;}}}for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {int a;read(a);if((i+j)&1) t.addedge(st,id[i][j][0],a);else t.addedge(id[i][j][1],ed,a);}}for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {int b;read(b);t.addedge(id[i][j][0],id[i][j][1],b);sum+=b;}}for(int x=1;x<=n;x++) {for(int y=1;y<=m;y++) {if((x+y)&1) {for(int k=0;k<4;k++) {int xx=x+b[k][0],yy=y+b[k][1];if(xx<=0||xx>n||yy<=0||yy>m) continue;for(int i=0;i<2;i++) t.addedge(id[x][y][i],id[xx][yy][i],inf);}}}}cout<<sum-t.solve(st,ed)<<endl;return 0;
}

2021-2022年度第三届全国大学生算法设计与编程挑战赛(秋季赛)- 占座位(最小割)相关推荐

  1. 2021-2022年度第三届全国大学生算法设计与编程挑战赛(夏季赛)

    2021-2022年度第三届全国大学生算法设计与编程挑战赛(夏季赛) 主要是用于记录涉及的知识点,本次比赛是团队赛. http://oj.saikr.com/contest/20/problems 部 ...

  2. 2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)题解(7道题)

    只有:B,D,E,G,I,K,L 正文 B:题目链接  Error 题目: 思路:二分 二分给出一个d,先考虑第一个数,让第一个数 r 为max(a[1]-d,0) 而且a[i]太小就直接返回NO,也 ...

  3. 2021-2022年度第三届全国大学生算法设计与编程挑战赛(秋季赛)- 分组(矩阵快速幂套NTT优化dp)

    题目链接:点击查看 题目大意:给出 nnn 个连续的小球,每次可以选择单独的一个或者相邻的两个小球分成一组,允许有剩余的小球,问恰好分成 k∈{1,2,3,⋯,m}k\in\{1,2,3,\cdots ...

  4. 2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)-正式赛 部分题解

    比赛链接 http://oj.saikr.com/contest/19 B.Error 思路 这道题其实我们贪心加上二分就能做了,首先我们贪心得把 b[1]b[1]b[1] 变得很小,然后构造 b[i ...

  5. 【算法】第三届全国大学生算法设计与编程挑战赛(冬季赛)

    7题金,6题银,5题铜 [参考:2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)题解_int 我的博客-CSDN博客] [参考:2021-2022年度第三届全国大学生算法设计与编程 ...

  6. 2022-2023年度第四届全国大学生算法设计与编程挑战赛(秋季赛)【热身赛】h-4题 花灯

    一.问题描述 二.分析: 此题的问题描述部分的第一句话:"花灯有n个,排列成l行供大家欣赏."中,"排列成l行"应与本题求解无关.由题意可知:n个花灯被均分为块 ...

  7. 第三届全国大学生算法设计与编程挑战赛 (冬季赛)部分题解

    部分题解 树的果实 题目描述 题目思路及代码 Error 题目描述 题目思路及代码 吃利息 题目描述 题目思路及代码 MP4 题目描述 题目思路及代码 展览 题目描述 题目思路及代码 礼物 题目描述 ...

  8. C:勇敢羊羊不怕困难!2022-2023年度第四届全国大学生算法设计与编程挑战赛(秋季赛)之羊驼

    目录 题目分析 程序设计 总体流程 信息输入 递归函数 完整代码 代码分析 题目分析 问题描述如图: 利用函数迭代,找出能走到出口的每一条路,取路径最短的路线. 程序设计 总体流程 输入相应的地图信息 ...

  9. 第三届全国大学生算法设计与编程挑战赛---K题 真假英雄

    真假英雄 Description xxx是一个热衷推理的小朋友.他喜欢看各种本格推理小说,更喜欢自己去参与到推理的过程中,所以每一次去恐怖密室时,他都不在意密室的npc,背景音乐,就是模拟医院里面病床 ...

最新文章

  1. (C++)除基取余法:将十进制数转化为Q进制数
  2. python3项目-把项目从Python2.x移植到Python3.x的经验总结
  3. RMQ(Range Minimum/Maximum Query)问题:
  4. getplotlyoffline(‘http://cdn.plot.ly/plotly-latest.min.js‘)无法下载如何解决
  5. 直流电动机matlab仿真实验,直流电动机的MATLAB仿真.doc
  6. 启明云端分享|sigmastar SSW101B WiFi 非信令测试说明
  7. Currency determination callback
  8. php string slice,substring()与str.slice()区别
  9. ActionScript 3 step by step (2) - 使用Trace()跟踪输出
  10. git remote 命令的用法
  11. Oracle下载 OPatch
  12. php 判断时间超过5分钟_视频超过5分钟怎么在微信中进行发送
  13. 如何在应用程序中隐藏2021款MacBook刘海?
  14. HTML开发者工具抓取所有图片,利用开发者工具,截取网页高清长图
  15. Lync Server 服务器版本升级
  16. 在计算机运行时 把程序和数据存放在内存中,单选(2.5分) 在计算机运行时,把程序和数据一样存放在内存中,这是1946年由__________领导的小组正式提出并论证的。‍...
  17. 一行python代码能实现什么丧心病狂的功能_一行Python 能实现什么丧心病狂的功能...
  18. Android MotionLayout As a Dancer
  19. 域名解析错误怎么办?
  20. 带宽与网速之间的关系

热门文章

  1. rocksdb写放大_Rocksdb的优劣及应用场景分析
  2. Spring注入总结
  3. 初步认识Volatile-一段代码引发的思考
  4. IDEA 集成Lombok 插件-使用插件
  5. 分布式文件系统研究-搭建图片服务虚拟主机
  6. 循环结构_do-while循环
  7. flume的概述和运行机制
  8. SpringCloud:Feign接口转换调用服务(Feign 基本使用、Feign 相关配置)
  9. 关于汽车领域的知识图谱实战入门
  10. 200808C阶段一点菜系统界面及运行