双倍经验:Luogu P5089 元素周期表CF1012B Chemical table:模拟赛搬的好题,有点厉害。赛时10min码的假贪心拿了五十多分,赢。

并查集思路 1

对于此类棋盘整行整列覆盖问题,有一个通用思路:把每一行和每一列看作一个点,那么原本棋盘上的格子就可以看作是连接这些点的边。例如一个点是 \((x,y)\) ,那么我们就可以把行 \(x\) 代表的点与列 \(y\) 代表的点连一条边。

这样做的原因是如果确定了行与列,那么我们就可以确定唯一的点。并且本题还是整行整列地进行覆盖的,数据范围较大,只能通过此类表达方式来把原来 \(10^{12}\) 级别的点,化为 \(10^{12}\) 级别的边;剩下点的个数就为 \(2 \times 10^6\) 级别。

一些这种图的性质:

  • 如果第 \(i\) 行与第 \(j\) 列联通,可以当成格子 \((i,j)\) 处有一个点。
  • 本质上是把每个已有的格子,从横纵两个方向散开直线,这些直线只要形成交点,就是一个连通块。在本题中这么应用,是因为只要有 \(3\) 个点,我们就可以确定一个矩形。

接下来思考核聚变的过程:

对于点 \((x_1,y_1),(x_1,y_2),(x_2,y_1),(x_2,y_2)\) 组成一个矩形 ,我们先假设 \((x_2,y_2)\) 还没有生成。

那么连出的图就长这样:(圆表示 \(x\) ,方表示 \(y\) 。)

可以发现,点 \(x_2\) 与点 \(y_2\) 已经是联通的了,并且由于上述的第一条性质:如果第 \(i\) 行与第 \(j\) 列联通,可以当成格子 \((i,j)\) 处有一个点。此时的点已经自动被拓展了出来。

于是,我们只需要把 \(n+m\) 个所有的点都合并成一个连通块,就可以了。

这个过程可以用并查集维护。

合并的次数就是连通块的个数 \(-1\) 。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,q,f[2000005],ans=0;
void init()
{
for(int i=1;i<=n+m;i++)f[i]=i;
}
int findf(int x)
{
if(f[x]!=x)f[x]=findf(f[x]);
return f[x];
}
void combine(int x,int y)
{
int fx=findf(x),fy=findf(y);
f[fx]=fy;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>q;
init();
while(q--)
{
int x,y;
cin>>x>>y;
combine(x,y+n);
}
for(int i=1;i<=n+m;i++)
{
ans+=(findf(i)==i);
}
cout<<ans-1;
return 0;
}

并查集思路 2

某位金钩爷的做法,有点复杂,但也好理解。这种做法是单纯从本题的生成点的性质入手,而上一种做法就是单纯从套路上入手。

首先我们画个图:

可以发现,如果相邻两行的同一列有棋子(蓝色部分),那么这两行就完全同步状态了。例如我们往第一行加上一些绿色点,那么我们下面的紫色部分也会加上一些点。他们的状态是完全同步的。

进一步拓展结论,就可以得到如果任意两行的同一列有棋子,那么这两行就同步状态了,所以他们就成连通块了。

最终我们拓展完后,一定会形成一些没有相同列的连通块。

于是我们一开始就把行看成点,对有相同列的进行合并,统计连通块个数(空行不能和空行算一个连通块)。

然后特判一下有没有空列,答案就是连通块个数 \(-1\) 加上空列个数。

比上一种好理解一点。代码就不写了,我懒。

二分图思路

和并查集思路 1 的做法差不多,把二分图分成上面行一部分,下面列一部分,然后照常合并。

然后遇到不连通的部分合并一下,统计一下就好了。基本和并查集一样。

代码就不写了,我懒。*2

Luogu P5089 元素周期表 / Codeforces 1012B Chemical table 题解 [ 并查集 ] [ 二分图 ] [ 图论建模 ] [ 棋盘覆盖问题 ]的更多相关文章

  1. Codeforces 1012B Chemical table (思维+二分图)

    <题目链接> 题目大意:给定一个n*m的矩阵网格,向其中加点,对于一个组成矩形的四个点中如果有三个点中有元素,那么第四个点中会自动产生新的元素.问你最少再加多少个点能够填满这个网格.解题分 ...

  2. Codeforces Round #345 (Div. 2) E. Table Compression 并查集

    E. Table Compression 题目连接: http://www.codeforces.com/contest/651/problem/E Description Little Petya ...

  3. Codeforces Round #345 (Div. 2) E. Table Compression 并查集+智商题

    E. Table Compression time limit per test 4 seconds memory limit per test 256 megabytes input standar ...

  4. Codeforces Round #345 (Div. 1) C. Table Compression (并查集)

    Little Petya is now fond of data compression algorithms. He has already studied gz, bz, zip algorith ...

  5. Codeforces 859E Desk Disorder:并查集【两个属性二选一】

    题目链接:http://codeforces.com/problemset/problem/859/E 题意: 有n个人,2n个座位. 给出这n个人初始的座位,和他们想坐的座位. 每个人要么坐在原来的 ...

  6. codeforces 456 E. Civilization(并查集+数的直径)

    题目链接:http://codeforces.com/contest/456/problem/E 题意:给出N个点,M条边,组成无环图(树),给出Q个操作,操作有两种: 1 x,输出x所在的联通块的最 ...

  7. CodeForces - 1209D Cow and Snacks 并查集

    CodeForces - 1209D 题意 现在n种点心,每种点心只有一份,有k位客人,每位客人有两种想要吃的点心,你可以安排他们进场的顺序,每位客人会吃掉所有他想要吃的,并且还没被吃掉的点心.如果客 ...

  8. Codeforces 699D Fix a Tree 并查集

    原题:http://codeforces.com/contest/699/problem/D 题目中所描述的从属关系,可以看作是一个一个块,可以用并查集来维护这个森林.这些从属关系中会有两种环,第一种 ...

  9. Codeforces 731C:Socks(并查集)

    http://codeforces.com/problemset/problem/731/C 题意:有n只袜子,m天,k个颜色,每个袜子有一个颜色,再给出m天,每天有两只袜子,每只袜子可能不同颜色,问 ...

  10. codeforces 400D Dima and Bacteria 并查集+floyd

    题目链接:http://codeforces.com/problemset/problem/400/D 题目大意: 给定n个集合,m步操作,k个种类的细菌, 第二行给出k个数表示连续的xi个数属于i集 ...

随机推荐

  1. Tornado框架之基础(一)

    知识点 了解什么是Tornado框架 了解Tornado与Django的区别 Tornado的安装 了解Tornado的原理 掌握Tornado的基本写法 掌握Tornado的基本模块 tornado ...

  2. 使用 yum 安装 nginx

    rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm ...

  3. 用人工智能模型预测股市和加密货币的K线图

    前一篇:<从爱尔兰歌曲到莎士比亚:LSTM文本生成模型的优化之旅> 前言:加密货币市场昨日大幅下跌,一天内市值蒸发逾70亿 人民币.有人可能会问,如果使用人工智能模型预测市场的涨跌,是否能 ...

  4. PM-软件最难的不是开发程序,而是需求

    最近几个月,关于人工智能的惊人文章在互联网泛滥.这也引发了很多人的担心--软件开发人员可能很快就会失业,被人工智能取代.他们想象所有的企业高管和产品研究人员将绕过大多数或所有的软件开发人员,直接要求人 ...

  5. vscode实现Markdown实时预览

    vscode - 插件搜索: Markdown Preview Enhanced 安装 然后打开vscode预览框,即可. That's ALL

  6. 09C++选择结构(3)——教学

    一.求3个整数中最小值 (第20课 初识算法) 题目:输入三个整数,表示梨的重量,输出最小的数. 方法1:经过三次两两比较,得出最小值. a<=b && a<=c min= ...

  7. iOS - 利用 UIBezierPath 绘制圆弧

    iOS - 利用 UIBezierPath 绘制圆弧 API UIBezierPath 绘制圆弧主要利用以下方法: open func addArc(withCenter center: CGPoin ...

  8. Flutter GestureDector点击空白区域不响应

    GestureDector点击空白区域不响应 当GestureDector嵌套Container时,当Container子组件为Text时,点击空白区域不响应点击事件 GestureDetector( ...

  9. 8.mysql表分区

    MySQL表分区 表分区是将⼀个表的数据按照⼀定的规则⽔平划分为不同的逻辑块,并分别进⾏物理存储,这个规则就叫做分区函数,可以有不同的分区规则 5.7可以通过show plugins语句查看当前MyS ...

  10. 【前端】解决盒子被撑大问题 box-sizing

    设置 box-sizing:border-box(原本的默认值为:content-box) box-sizing: content-box;/*盒子宽度=CSS中设置的width+border+pad ...