USACO20JAN Cave Painting 并查集
Posted enisp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USACO20JAN Cave Painting 并查集相关的知识,希望对你有一定的参考价值。
一开始我想的是从地图中弄出一个森林来,这样确实可行,但是太麻烦了
事实上,我们并不一定需要把建出来
从最低海拔往上统计答案,考虑当两个联通合并会对答案造成什么影响:新的联通块的方案数为两个联通块的乘积(或者说所有合并了的联通块的乘积,因为有可能有多个联通块合并),当这一层计算完后,再给这一层的块的答案加一,表示全部都有水的情况
使用并差集来维护联通块就行了
统计最终时,我们把不同联通块的答案乘起来从而得到最终的答案
注意需要开long long
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define gi get_int()
#define int long long
const int MAXN = 1001 * 1001;
const int MOD = 1e9 + 7;
int get_int()
{
int x = 0, y = 1;
char ch = getchar();
while (!isdigit(ch) && ch != \'-\')
ch = getchar();
if (ch == \'-\')
y = -1, ch = getchar();
while (isdigit(ch))
x = x * 10 + ch - \'0\', ch = getchar();
return x * y;
}
int map[1001][1001], vis[MAXN], toBeAdd[MAXN];
int fa[MAXN], val[MAXN];
long long ans = 1;
int getFa(int u)
{
return fa[u] == u ? u : fa[u] = getFa(fa[u]);
}
int getPos(int x, int y)
{
return x * 1001 + y;
}
signed main()
{
int n = gi, m = gi;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
char ch;
std::cin >> ch;
if (ch == \'#\')
map[i][j] = -1;
if (ch == \'.\')
map[i][j] = 1;
}
}
for (int i = 0; i < MAXN; i++)
fa[i] = i, val[i] = 1;;
for (int i = n - 2; i >= 0; i--) {
/*
int cnt = 0, flag = 0;
for (int j = 0; j < m; j++) {
if (map[i + 1][j] == -1 && flag == 1) {
if (cnt == 0 && vis[getFa(getPos(i + 1, j - 1))] == 0) {
getAns(getPos(i + 1, j - 1));
std::cout << i + 2 << \' \' << j << std::endl;
vis[getFa(getPos(i + 1, j - 1))] = 1;
}
cnt = 0;
flag = 0;
}
if (map[i + 1][j] == 1)
flag = 1;
if (map[i][j] == 1 && map[i + 1][j] == 1)
cnt++;
}
*/
for (int j = 1; j < m; j++) {
if (map[i][j] == -1) continue;
if (map[i][j - 1] == 1) {
int u = getFa(getPos(i, j)), v = getFa(getPos(i, j - 1));
fa[v] = u;
}
}
int tmp = 0;
for (int j = 1; j < m; j++) {
if (map[i][j] == -1) continue;
if (map[i + 1][j] == 1) {
int u = getFa(getPos(i, j)), v = getFa(getPos(i + 1, j));
if (u == v) continue;
fa[v] = u;
(val[u] = val[u] * val[v]) %= MOD;
}
}
for (int j = 1; j < m; j++) {
if (map[i][j] == -1) continue;
if (toBeAdd[getFa(getPos(i, j))] == 1) continue;
toBeAdd[getFa(getPos(i, j))] = 1;
val[getFa(getPos(i, j))]++;
}
for (int j = 1; j < m; j++) {
if (map[i][j] == -1) continue;
toBeAdd[getFa(getPos(i, j))] = 0;
}
}
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
int now = getFa(getPos(i, j));
if (vis[now] == 1) continue;
vis[now] = 1;
(ans *= val[now]) %= MOD;
//std::cout << val[now] << std::endl;
}
std::cout << ans;
return 0;
}
以上是关于USACO20JAN Cave Painting 并查集的主要内容,如果未能解决你的问题,请参考以下文章
[luogu P2205] [USACO13JAN]画栅栏Painting the Fence
洛谷P2205 [USACO13JAN]画栅栏Painting the Fence
luogu4187 [USACO18JAN]Stamp Painting (dp)