http://codeforces.com/contest/723/problem/D

这题是只能把小河填了,题目那里有写,其实如果读懂题这题是挺简单的,预处理出每一块的大小,排好序,从小到大填就行了。

以前找这些块的个数用的是dfs。现在这次用并查集做下。

首先要解决的是,二维坐标怎么并查集,以前的并查集都是一维的,现在是两个参数,那么就考虑离散,每对应一个点,离散到一个独特的一维数值即可。我用的公式的50 * x + y。这样得到的数值是唯一的。所以可以快乐地并查集了。

那么遇到一个'.',我们需要它和其他合并,思路就是观察其上面和左边是否存在'.',如果存在,就合并到左边(上面),没有,那就是自己一个块了。

有顺序的,检查完上面,合并完(现在爸爸是上面那个),还要检查左边,如果有,左边的就要合并过来。这样爸爸就只是上面那个了。

为什么要这样做呢?因为考虑下这个

***.**

*. ..**

枚举到加粗那个的时候,如果你只向左合并,则遗漏了上面那个,向上合并,又会使得左边的被算作不同的块。GG

所以是需要两边判断,同时合并的。注意合并的方向是固定的,需要及时选择那个是爸爸

然后就是排序删除了,每个点的爸爸是固定的,用个标记数组标记下删除了那个爸爸,输出的时候对应一下 就好

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 70 * 70;
char str[50 + 20][50 + 20];
int fa[maxn];
LL size[maxn];
int calc(int x, int y) {return 50 * x + y;
}
int find(int x) {if (fa[x] == x) return x;else return fa[x] = find(fa[x]);
}
void merge(int x, int y) {x = find(x);y = find(y);if (x != y) {fa[y] = x;size[x] += size[y];}
}
int del[maxn];
struct node {LL size;int FA;bool operator < (const struct node &rhs) const {return size < rhs.size;}node(LL aa, int bb) : size(aa), FA(bb) {}
};
multiset<struct node>ss;
bool used[maxn];
void work() {int n, m, k;scanf("%d%d%d", &n, &m, &k);for (int i = 1; i <= n; ++i) {scanf("%s", str[i] + 1);}for (int i = 0; i <= maxn - 1; ++i) {size[i] = 1;fa[i] = i;}for (int i = 1; i <= n; ++i) {size[calc(i, 1)] = inf;size[calc(i, m)] = inf;}for (int i = 1; i <= m; ++i) {size[calc(1, i)] = inf;size[calc(n, i)] = inf;}for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {if (str[i][j] == '.') {if (str[i - 1][j] == '.' && i - 1 >= 1) {merge(calc(i - 1, j), calc(i, j));}if (str[i][j - 1] == '.' && j - 1 >= 1) merge(calc(i, j), calc(i, j - 1));}}}for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {if (str[i][j] == '*') continue;int FA = find(calc(i, j));if (used[FA]) continue;if (size[FA] >= inf) continue;ss.insert(node(size[FA], FA));used[FA] = 1;}}multiset<struct node> :: iterator it = ss.begin();int cut = ss.size() - k;int ans = 0;while (cut--) {del[it->FA] = 1;ans += size[it->FA];it++;}printf("%d\n", ans);for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {int FA = find(calc(i, j));if (del[FA]) {printf("*");} else printf("%c", str[i][j]);}printf("\n");}
}int main() {
#ifdef localfreopen("data.txt","r",stdin);
#endifwork();return 0;
}

View Code

转载于:https://www.cnblogs.com/liuweimingcprogram/p/5933324.html

Codeforces Round #375 (Div. 2) D. Lakes in Berland 并查集相关推荐

  1. Codeforces Round #548 (Div. 2) C. Edgy Trees(并查集+快速幂)

    思路用并查集统计一个连通块的节点个数,最后用总的减去他,设x是连通块的节点个数,o个联通块 #include<bits/stdc++.h> #define fi first #define ...

  2. Codeforces Round #218 (Div. 2) D. Vessels(思维 并查集)

    题意:从上到下有n个杯子,编号从1到n.每个杯子有一定体积v[i]. 两种操作:1 x y, 向x水杯倒y水; 2 x, 询问x水杯有多少水. (水杯水溢出会往下流) n,q <= 2e5 思路 ...

  3. codeforces723 D. Lakes in Berland(并查集)

    题目链接:codeforces723 D. Lakes in Berland 参考博客:http://www.cnblogs.com/Geek-xiyang/p/5930245.html 1 #inc ...

  4. Codeforces Round #375 (Div. 2) F. st-Spanning Tree 生成树

    F. st-Spanning Tree 题目连接: http://codeforces.com/contest/723/problem/F Description You are given an u ...

  5. Codeforces Round #375 (Div. 2) B. Text Document Analysis(字符串处理,简单题目)

    题目链接:http://codeforces.com/contest/723/problem/B [分析]求不在括号里的单词的长度和在括号里的单词的个数.立个flag表示所处状态就好了,0表示不在括号 ...

  6. Codeforces Round #375 (Div. 2)

    这是我打的第一场现场CF,才涨了4分= =,太菜啦.. 第一题,超级大水题,不说了.. 第二题,也挺水的,要注意的是,最后一个字符如果不是下划线或者括号结束的话,仍然要判断那个单词.因为这点WA了好多 ...

  7. Codeforces Round #506 (Div. 3)

    Codeforces Round #506 (Div. 3) 实习期间事不多,对div3 面向题解和数据编程了一波 A. Many Equal Substrings 题目链接 A题就是找后缀和前缀重合 ...

  8. Codeforces Round #563 (Div. 2)/CF1174

    Codeforces Round #563 (Div. 2)/CF1174 CF1174A Ehab Fails to Be Thanos 其实就是要\(\sum\limits_{i=1}^n a_i ...

  9. 构造 Codeforces Round #302 (Div. 2) B Sea and Islands

    题目传送门 1 /* 2 题意:在n^n的海洋里是否有k块陆地 3 构造算法:按奇偶性来判断,k小于等于所有点数的一半,交叉输出L/S 4 输出完k个L后,之后全部输出S:) 5 5 10 的例子可以 ...

最新文章

  1. Python基本语法_函数属性 参数类型 偏函数的应用
  2. SciSharpCube:容器中的SciSharp,.NET机器学习开箱即用
  3. erp生产管理系统流程_企业生产管理好帮手——ERP智能管理系统
  4. ssm数据库异常问题
  5. 计算机学习知识,如何学习计算机知识呢
  6. 将参数传递给Bash函数
  7. linux的引导过程和服务控制
  8. 2022焊工(初级)操作证考试题库及答案
  9. 微信小程序轮播图实现详解
  10. Linux固态硬盘 设置写入缓存,Win10下的写入缓存策略严重影响SSD硬盘的性能!
  11. opencv的imwrite设置图片压缩率
  12. AcWing - 寒假每日一题2023(DAY 11——DAY 15)
  13. 孑然一身,离人何曾是归人
  14. 零基础能不能学习web前端开发?【爱创课堂专业前端培训】
  15. html,css维护优化,网站CSS代码优化的7个原则
  16. Karl Guttag:Magic Leap 2与HoloLens 2对比
  17. Android内存相关
  18. 车站信息管理系统Android,车站售票管理信息系统
  19. 双11,当当图书大放价,专属200-30优惠码免费送
  20. C语言printf %f怎么去除末尾的0

热门文章

  1. MySQL编程(0) - Mysql中文乱码问题解决方案
  2. set uid,set gid,sticky bit的三个权限的详细说明
  3. 双向滚动scrollview
  4. 基于地图开发控件GMap.Net 使用 (一) 原创
  5. 不同组织间的邮件收发
  6. 通过Visual Studio 2005的项目模板来加速开发过程
  7. 网络工程师的职业发展路线
  8. Linux 编程中的API函数和系统调用的关系【转】
  9. iOS的那个漏洞并不只是影响苹果设备CVE-2017-6975 Google称影响了所有使用Broadcom Wi-Fi SoC的设备...
  10. Linux 编译内核