ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

并查集的高级应用

2022-05-01 23:03:16  阅读:207  来源: 互联网

标签:r1 填充 int 查集 高级 r2 应用 c2 c1


1 给定一个 n×m 的矩阵,其中 q 个位置已经被填充。
2 有一条规则,如果 (r1,c1)(r1,c1) ,(r1,c2)(r1,c2),(r2,c1)(r2,c1) 均被填充,则 (r2,c2)(r2,c2) 也被填充。任何被其他三个位置生成的位置,也可以继续生成其他位置。
问最少需要再人为填充多少元素,使矩阵被填满。 3 The first line contains three integers n, m, q (1 ≤ n, m ≤ 200 000; 0 ≤ q ≤ min(n·m, 200 000)),
the chemical table dimensions and the number of elements scientists already have. 4 5 The following q lines contain two integers ri, ci (1 ≤ ri ≤ n, 1 ≤ ci ≤ m),
each describes an element that scientists already have. All elements in the input are different.

 

思路来自这个大佬:

题解
我们考虑自动填充的规则,又三个点自动生成第四个点。如果 (r1,c1)(r1,c1) ,(r1,c2)(r1,c2),(r2,c1)(r2,c1) 均被填充,则可以看成:

(r1,c1)(r1,c1):r1r1 和 c1c1 被联系起来
(r1,c2)(r1,c2):r1r1 和 c2c2 被联系起来
由 1,2→1,2→ c1c1 和 c2c2 被联系起来
(r2,c1)(r2,c1):r2r2 和 c1c1 被联系起来
由 3,4→3,4→ r2r2 和 c2c2 被联系起来,即有 (r2,c2)(r2,c2) 被填充
这两个模型是等价的。至此,我们把每个边的标号和每个列的标号都看成抽象图中的点,每个给出的点 (r,c)看成一个关于点 r 和点 c 属于同一集合的声明。故我们可以使用并查集维护,计算出当前矩阵中独立集合的数量 NN。

考虑需要人工合并的次数(即认为填充元素的数目)。考虑当前矩阵中未被填充的点,人工填充这个点一定可以实现两个集合的合并,总集合数即减 1。每次人工填充后均自动填充所有可以被自动填充的点。故 N−1 次人工填充后,将全部属于一个集合,矩阵被填满,所以原题的答案即为 N−1。
————————————————
版权声明:本文为CSDN博主「hyp1231」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hyp1231/article/details/81295464

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 2 * 1e5 + 10;
 6 int p[N * 2];
 7 int n, m, q;
 8 int find(int x)
 9 {
10     if (p[x] != x)
11         p[x] = find(p[x]);
12     return p[x];
13 }
14 int main()
15 {
16     int r, c;
17     scanf("%d%d%d", &n, &m, &q);
18     for (int i=1;i<=n+m;i++) p[i]=i;
19     while (q--)
20     {
21         scanf("%d%d", &r, &c);
22         int fr = find(r), fc = find(c + n);//对于c+n要好好说一番:我们将每一行标上序列 1~n ,为了不重复,我们将每一列从 n+1开始标:
//一直到n+m,正好,m列,对应是n+1~n+m,m个元素。
23 if (fr != fc) 24 p[fc] = fr; 25 } 26 int ans = 0; 27 for (int i = 1; i <= n + m; i++) 28 { 29 if (p[i] == i)//当ans为nn时,当nn>=2,从中取两个元素ai,aj,说明(ai,aj)这个点一定是没有的,否则即使p[ai]==ai,但p[aj]应该==ai;
//所以我们要人工加上这个点;当nn<2 ,即nn=1时,这个一定是全部联通,其作为全部的祖父的情况。 30 ans++; 31 } 32 if (ans == 0) 33 printf("%d", ans); 34 else 35 printf("%d", ans - 1); 36 return 0; 37 }

 

标签:r1,填充,int,查集,高级,r2,应用,c2,c1
来源: https://www.cnblogs.com/cilinmengye/p/16214623.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有