Grid and Tokens

题目大意

给定 \(n\) 个点和一个 \(H\times W\) 的网格,每个点可以放置在 \((A_i,B_i)\) 到 \((C_i,D_i)\) 的矩形中或不放,每一行或一列只能放置一个点,求最多能放多少个点。

思路分析

首先看数据范围,再结合题目给的限制条件,容易发现这是一道网络流。

考虑建图,因为行和列存在限制条件而网格中的点不存在,所以可以考虑将每一行和每一列分别建成一个点。再建立一个超级源点和超级汇点,源点向行连边权为 \(1\) 的边,列向汇点连边权为 \(1\) 的边。 表示每一行和每一列只能放一个点的限制条件。

对于一个点的矩形放置范围,可以转换为行 \(A_i\sim C_i\) 向该点连边权为 \(1\) 的边,该点向列 \(B_i\sim D_i\) 连边权为 \(1\) 的边,表示每一行和每一列对于点的匹配。

同时,点存在容量的限制,所以要将点拆成入点和出点,再连边。

综上所述,建图过程如下:

  • 建立源点,汇点。

  • 对于每一行和每一列建立一个点,源点向行连边权为 \(1\) 的边,列向汇点连边权为 \(1\) 的边。

  • 对于每一个点,建立入点和出点,入点向出点连边权为 \(1\) 的边,行 \(A_i\sim C_i\) 向入点连边权为 \(1\) 的边,出点向列 \(B_i\sim D_i\) 连边权为 \(1\) 的边。

因为流网络是单位网络,所以时间复杂度为 \(O(n^3)\)。(\(n,H,W\) 同阶)

代码

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue> using namespace std;
const int N=200100;
#define inf 0x3f3f3f3f int n,m,k,idx=1,S,T,in1,in2,in3,in4,cnt;
int to[N],nxt[N],head[N],w[N];
int cur[N],d[N]; queue <int> q; void add(int u,int v,int c){
idx++;to[idx]=v;nxt[idx]=head[u];head[u]=idx;w[idx]=c;
idx++;to[idx]=u;nxt[idx]=head[v];head[v]=idx;w[idx]=0;
} bool bfs(){
memset(d,-1,sizeof d);
while(!q.empty()) q.pop();
cur[S]=head[S];
q.push(S);d[S]=0;
while(!q.empty()){
int now=q.front();q.pop();
for(int i=head[now];i;i=nxt[i]){
int v=to[i];
if(~d[v]||!w[i]) continue;
d[v]=d[now]+1;
cur[v]=head[v];
if(v==T) return 1;
q.push(v);
}
}
return 0;
} int dfs(int s,int lim){
if(s==T) return lim;
int flow=0;
for(int i=cur[s];i&&flow<lim;i=nxt[i]){
int v=to[i];cur[s]=i;
if(d[v]!=d[s]+1||!w[i]) continue;
int t=dfs(v,min(w[i],lim-flow));
if(!t) d[v]=-1;
w[i]-=t;w[i^1]+=t;flow+=t;
}
return flow;
} int dinic(){
int ans=0,flow=0;
while(bfs()) while(flow=dfs(S,inf)) ans+=flow;
return ans;
} int main(){
scanf("%d%d%d",&n,&m,&k);
S=N-5;T=N-6;cnt=n+m+1;
for(int i=1;i<=n;i++) add(S,i,1);//源点->行
for(int i=n+1;i<=n+m;i++) add(i,T,1);//列->汇点
for(int i=1;i<=k;i++){
scanf("%d%d%d%d",&in1,&in2,&in3,&in4);
for(int i=in1;i<=in3;i++) add(i,cnt,1);//行->入点
for(int i=n+in2;i<=n+in4;i++) add(cnt+1,i,1);//出点->列
add(cnt,cnt+1,1);//入点->出点
cnt+=2;
}
cout<<dinic()<<'\n';
return 0;
}

[ABC205F] Grid and Tokens 题解的更多相关文章

  1. 算法与数据结构基础 - 贪心(Greedy)

    贪心基础 贪心(Greedy)常用于解决最优问题,以期通过某种策略获得一系列局部最优解.从而求得整体最优解. 贪心从局部最优角度考虑,只适用于具备无后效性的问题,即某个状态以前的过程不影响以后的状态. ...

  2. 【题解】AT2043 AND Grid

    [题解]AT2043 AND Grid 我们考虑直接构造两个互补的图切分别联通的图,然后原图有的大家都有就构造完成了. #include<iostream> #include<cst ...

  3. 题解报告:poj 2185 Milking Grid(二维kmp)

    Description Every morning when they are milked, the Farmer John's cows form a rectangular grid that ...

  4. ZOJ - 3781 Paint the Grid Reloaded 题解

    题目大意: 给一个n*m的X O构成的格子,对一个点操作可以使与它相连通的所有一样颜色的格子翻转颜色(X—>O或O—>X),问给定的矩阵最少操作多少次可以全部变成一样的颜色. 思路: 1. ...

  5. POJ2185 Milking Grid 题解 KMP算法

    题目链接:http://poj.org/problem?id=2185 题目大意:求一个二维的字符串矩阵的最小覆盖子矩阵,即这个最小覆盖子矩阵在二维空间上不断翻倍后能覆盖原始矩阵. 题目分析:next ...

  6. Codeforces Round #597 (Div. 2) D. Shichikuji and Power Grid 题解 最小生成树

    题目链接:https://codeforces.com/contest/1245/problem/D 题目大意: 平面上有n座城市,第i座城市的坐标是 \(x[i], y[i]\) , 你现在要给n城 ...

  7. CF1703E Mirror Grid 题解

    给定一个矩阵,判断最少将多少个格反转后使得旋转零度,九十度,一百八十度,二百七十度相等. 枚举矩阵每个位置是 \(0\) 还是 \(1\),若已经判断过则跳过,全统 \(1\) 和全统 \(0\) 取 ...

  8. LeetCode OJ 题解

    博客搬至blog.csgrandeur.com,cnblogs不再更新. 新的题解会更新在新博客:http://blog.csgrandeur.com/2014/01/15/LeetCode-OJ-S ...

  9. leetcode & lintcode 题解

    刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...

  10. NBUT1541 Rainwater 题解

    http://cdn.ac.nbutoj.com/Problem/view.xhtml?id=1541 When rain, nocLyt discovered a magical phenomeno ...

随机推荐

  1. Windows 环境下Docker 安装伪分布式 Hadoop

    1.环境 Windows 11 Docker 20.0.2 2.拉取镜像 我选择 ubuntu20.04: docker pull ubuntu:20.04 然后我们用命令看一下本地镜像: docke ...

  2. border属性之border-radius

    border-radius - 指定每个圆角 如果你在 border-radius 属性中只指定一个值,那么将生成 4 个 圆角. 但是,如果你要在四个角上一一指定,可以使用以下规则: 四个值: 第一 ...

  3. 如何使用CCXT交易数字货币现货

    更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 数字货币现货标准化接口 数字货币市场与股票.期货市场最大的不同点在于数字货币主流交易所数量很多.举个例子 ...

  4. 利用InnoStep在VS编译时自动构建安装包

    摘要 很多同学在C/S开发领域或多或少都可能会遇到需要制作安装包的场景,打包的工具也是五花八门,例如有NSIS.InstallShield.Wix Toolset.ClickOnce等等,这里以Inn ...

  5. Python中的弱引用与基础类型支持情况探究

    背景 最近有一个业务场景需要用Python自行实现一个简单的LRU cache,不可避免的接触到了弱引用这一概念,这里记录一下. 强引用 Python内存回收由垃圾回收器自动管理,当一个对象的引用计数 ...

  6. shell 并发

    #!/bin/bash # 设置并发数 thread_num=3 # 创建管道文件 FIFO=/tmp/$$-FIFO mkfifo $FIFO # 使用句柄打开管道文件 exec 1000<& ...

  7. grafana Variables 变量的使用

    概念澄清 A variable is a placeholder for a value. # 变量是值的占位符. # 参考文档:https://grafana.com/docs/grafana/la ...

  8. 树形DP + 换根DP

    树形DP--基础 P1352 没有上司的舞会 设 \(f[i][0/1]\) 表示第 \(i\) 个人不去或者去. 如果第 \(i\) 个人没去,那么下属可去可不去,所以 \(f[i][0] = \s ...

  9. VScode 中golang 基准测试 go test -bench .

    目的:基准测试的主要目的是比较不同实现方式之间的性能差异,找出性能瓶颈. 1 准备以_test.go结尾文件和导入testing包 在命名文件时需要让文件必须以_test结尾,在文件中导入testin ...

  10. [jenkins]连接git仓库

    连接gitlab 在jenkins添加全局凭据,类型为"ssh username with private key",填写git用户名和ssh私钥信息(注意是git客户端所在机器的 ...