AcWing 1250. 格子游戏
AcWing 1250. 格子游戏
鉴定为简单的并查集模板题, 下面介绍并查集以及该题思路
并查集是什么?
并查集是一种数据结构, 通过一棵树来存储一组有关联的数据, 以此题为例, 即是用一颗树来维护一段由边串连起来的连通块, 主要操作有查找祖先节点以及合并两个并查集, 会维护自己的父亲节点。
查找祖先节点\((find)\)
最朴素的做法便是沿着父亲节点向上爬到根节点。
int find(int x)
{
if(x == fa[x])
{
return x;
}
return find(fa[x]);
}
但是这样的时间复杂度在一个有\(n\)个节点的并查集下操作, 时间复杂度最高可达\(O(n)\), 很明显, 这需要优化。
所以我们可以用一种名为路径压缩的办法, 用\(fa[]\)数组直接存储根节点, 在返回结果的同时更新\(fa[]\)数组即可。
int find(int x)
{
if(x == fa[x])
{
return x;
}
return fa[x] = find(fa[x]);
}
合并两个并查集\((merge)\)
将一个节点\(x\)的根节点\(find(x)\)设为另一个节点\(y\)根节点\(find(y)\)的父亲节点, 特殊的, 若\(find(x) = find(y)\), 则说明两个节点在同一个并查集内, 无需合并。

bool merge(int x, int y)
{
int fx = find(x), fy = find(y);
if(fx == fy)
{
return 0;
//在同一个并查集内, 无需合并
}
fa[fx] = fy;
return 1;
//合并成功
}
本题思路
考虑将一段联通的点存入一个并查集, 建立一条边时, 将边的两个端点所在的并查集合并, 若两点已在同一个并查集内, 则说明出现环。
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
int pos = (i - 1) * n + j;
fa[pos] = pos;
}
}
for(int i = 1; i <= m; i++)
{
int x, y, p1, p2;
char dir;
cin >> x >> y >> dir;
p1 = (x - 1) * n + y;
if(dir == 'D')
{
p2 = p1 + n;
}
else
{
p2 = p1 + 1;
}
if(!merge(p1, p2))
{
cout << i << '\n';
return 0;
}
}
cout << "draw" << '\n';
return 0;
}

浙公网安备 33010602011771号