之前忘了并查集使用的方式,导致我把图中的11张图看成了各自的一类,然后就悲剧了=-=
简述这道题的意思,就是有11种suqare然后将这些可以组成各种大小的田地。现在它给你一块由这些suqare组成的田地
,因为每块地都有pipe,要保证这些田都被灌溉你要判断这块地需要多少个wellspring。
首先说下并查集的思路:题目要求是输入m行,n列,而且m和n是不超过50,算出来是2500,说明使用并查集是可以解决的
时间复杂度是O(m*n),并查集最需要注意的地方就是要注意初始化。这道题wa了4次,前两次是没找出自己的并查集是写错的
,后两次改成正确的并查集,然而却忘了初始化_(:зゝ∠)_。
#include<iostream>
#include<fstream>
#include<cstring>
using namespace std;
struct Squares
{
bool up;
bool down;
bool left;
bool right;
int root;
};
int p[2510];
Squares S[12];
int disjoint[12] = { 0 };
bool isjudge[2510] = { 0 };
int m, n;
int map[60][60];
void init()
{
S[1].up = true;
S[1].down = false;
S[1].left = true;
S[1].right = false;
S[1].root = 1;
S[2].up = true;
S[2].down = false;
S[2].left = false;
S[2].right = true;
S[2].root = 2;
S[3].up = false;
S[3].down = true;
S[3].left = true;
S[3].right = false;
S[3].root = 3;
S[4].up = false;
S[4].down = true;
S[4].left = false;
S[4].right = true;
S[4].root = 4;
S[5].up = true;
S[5].down = true;
S[5].left = false;
S[5].right = false;
S[5].root = 5;
S[6].up = false;
S[6].down = false;
S[6].left = true;
S[6].right = true;
S[6].root = 6;
S[7].up = true;
S[7].down = false;
S[7].left = true;
S[7].right = true;
S[7].root = 7;
S[8].up = true;
S[8].down = true;
S[8].left = true;
S[8].right = false;
S[8].root = 8;
S[9].up = false;
S[9].down = true;
S[9].left = true;
S[9].right = true;
S[9].root = 9;
S[10].up = true;
S[10].down = true;
S[10].left = false;
S[10].right = true;
S[10].root = 10;
S[11].up = true;
S[11].down = true;
S[11].left = true;
S[11].right = true;
S[11].root = 11;
}
void initroot()
{
for (int i = 0; i <= m*n; i++)
{
p[i] = i;
}
}
int findroot(int a)
{
int root = a;
while (p[root] != root)
root = p[root];
int i = a, j;
while (i != root)
{
j = p[i];
p[i] = root;
i = j;
}
return root;
}
void merge(int a, int b)
{
int fx = findroot(a), fy = findroot(b);
if (fx != fy)
{
p[fx] = fy;
}
}
int ans;
void solve()
{
ans = 0;
int loc;
int locup;
int locdown;
int locleft;
int locright;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
loc = map[i][j];
if (i - 1 >= 0)//up is right
{
locup = map[i - 1][j];
if (S[locup].down&&S[loc].up)
{
merge(i*n + j, (i - 1)*n + j);
}
}
if (i + 1 < m)//down is right
{
locdown = map[i + 1][j];
if (S[locdown].up&&S[loc].down)
{
merge(i *n + j, (i + 1)*n + j);
}
}
if (j + 1 < n)//right is right
{
locright = map[i][j + 1];
if (S[locright].left&&S[loc].right)
{
merge(i *n + j, i*n + j + 1);
}
}
if (j - 1 >= 0)
{
locleft = map[i][j - 1];
if (S[locleft].right&&S[loc].left)
{
merge(i*n + j, i*n + j - 1);
}
}
}
}
for (int i = 0; i < m*n; i++)
findroot(i);
for (int i = 0; i < m*n; i++)
{
if (isjudge[p[i]] == false)
{
ans++;
isjudge[p[i]] = true;
}
}
printf("%d\n", ans);
}
int main()
{
init();
while (scanf_s("%d%d", &m, &n))
{
//getchar();
initroot();
memset(isjudge, false, sizeof(isjudge));
memset(map, 0, sizeof(map));
if (m + n == -2)
break;
char c;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cin >> c;
//scanf_s("%c", &c);
map[i][j] = c - 'A' + 1;
}
//getchar();
}
solve();
}
}