Codeforces Round #375 (Div. 2) D. Lakes in Berland 并查集
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 并查集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: walle(瓦力)部署系统的安装和简单使
- 下一篇: [原创]java WEB学习笔记86:H