AcWing1250格子游戏(并查集)

题目地址https://www.acwing.com/problem/content/1252/

题目描述

Alice和Bob玩了一个古老的游戏:首先画一个 n×nn×n 的点阵(下图 n=3n=3 )。

接着,他们两个轮流在相邻的点之间画上红边和蓝边:

1.png

直到围成一个封闭的圈(面积不必为 11)为止,“封圈”的那个人就是赢家。因为棋盘实在是太大了,他们的游戏实在是太长了!

他们甚至在游戏中都不知道谁赢得了游戏。

于是请你写一个程序,帮助他们计算他们是否结束了游戏?

输入格式

输入数据第一行为两个整数 nn 和 mm。nn表示点阵的大小,mm 表示一共画了 mm 条线。

以后 mm 行,每行首先有两个数字 (x,y)(x,y),代表了画线的起点坐标,接着用空格隔开一个字符,假如字符是 DD,则是向下连一条边,如果是 RR 就是向右连一条边。

输入数据不会有重复的边且保证正确。

输出格式

输出一行:在第几步的时候结束。

假如 mm 步之后也没有结束,则输出一行“draw”。

数据范围

1n2001≤n≤200,
1m24000

题解:第一眼看见这道题以为超级难,结果听大佬一讲发现就是一道裸的并查集。。。。。。

题目问你什么时候结束,那么结束的标志就是产生一个环,那么怎么判定是否产生了一个环。这就需要并查集直接操作就可以了,如果当前这条边的两端在同一个集合中,那么就是一个环。那么剩下的就只有一个小问题了,就是并查集一般是在一维空间下,这里就需要将二维空间转换为一维空间,x*n+y,只要x,y都是从0开始的就可以了。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=210;
const int M=24010;
int fa[N*M],n,m;
int find(int x){
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}
int main(){
    cin>>n>>m;
    int ans=0;
    char ch;
    for(int i=1;i<=n*m;i++) fa[i]=i;
    for(int i=1,x,y,a,b;i<=m;i++){
        cin>>x>>y>>ch;
        a=x*n+y;
        if(ch=='D') x++;
        else y++;
        b=x*n+y;
        int ra=find(a),rb=find(b);
        if(!ans&&ra==rb) {
            ans=i;
        }
        fa[ra]=rb;
    }
    if(ans) cout<<ans;
    else cout<<"draw";
    return 0;
} 

写于:2020/8/22 18:10


作者:孙建钊
出处:http://www.cnblogs.com/sunjianzhao/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/sunjianzhao/p/13546541.html