NOJ [1301] Gopher Hole

来源:互联网 发布:百度派 知乎 编辑:程序博客网 时间:2024/05/18 00:53
链接地址:http://ac.nbutoj.com/Problem/view.xhtml?id=1301

死月最爱讲故事了,这次他讲了个很有趣的故事。
很久很久以前,有一只地鼠,他很调皮,很喜欢打洞。
这次他来到一块 N * N 的地域,然后开始打洞。
当输入是Out的时候,表示他将在(x, y)打洞,当有两个洞是拥有公共的边时,那么这两个洞是连通的,也就是说是属于同一个洞的。
那么,每挖一次洞,就使用一次并查集。

以下是我出题代码。

#include <set>
#include <list>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;

#define N 105

int num;
int cnum;
int hole[N][N];
int rank[N * N];
int v[N * N];
int dir[4][2] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};

int find_set(int x)
{
if (v[x] != x) v[x] = find_set(v[x]);
return v[x];
}

void Union(int x, int y)
{
if (rank[x] > rank[y]) v[y] = x;
else if (rank[x] < rank[y]) v[x] = y;
else
{
v[x] = y;
rank[y]++;
}
}

int main()
{
int n, m, s1, s2;
char cmd[5];

//freopen("in.in", "r", stdin);
//freopen("out.out", "w", stdout);
while (~scanf("%d%d", &n, &m))
{
num = cnum = 0;
memset(hole, 0, sizeof(hole));
memset(rank, 0, sizeof(rank));
for (int i = 0; i <= n * n; i++) v[i] = i;
for (int i = 0; i < m; i++)
{
scanf("%s", cmd);
if (cmd[0] == 'O')
{
int p;
int x, y;
scanf("%d%d", &x, &y);
x++;
y++;
if (hole[x][y]) continue;
hole[x][y] = ++cnum;
if (!hole[x - 1][y] && !hole[x + 1][y] && !hole[x][y + 1] && !hole[x][y - 1])
{
num++;
continue;
}
p = 1;
for (int j = 0; j < 4; j++)
{
int xx, yy;
xx = x + dir[j][0];
yy = y + dir[j][1];
if (hole[xx][yy])
{
s1 = find_set(hole[x][y]);
s2 = find_set(hole[xx][yy]);
if (s1 != s2)
{
p--;
Union(s1, s2);
}
}
}
num += p;
}
else printf("%d\n", num);
}
}

return 0;
}

0 0
原创粉丝点击