题目
题目描述
Alice和Bob玩了一个古老的游戏:首先画一个n × n的点阵(下图n = 3)
接着,他们两个轮流在相邻的点之间画上红边和蓝边:
直到围成一个封闭的圈(面积不必为1)为止,“封圈”的那个人就是赢家。因为棋盘实在是太大了(n ≤ 200),他们的游戏实在是太长了!他们甚至在游戏中都不知道谁赢得了游戏。于是请你写一个程序,帮助他们计算他们是否结束了游戏?
输入格式
输入数据第一行为两个整数n和m。m表示一共画了m条线。
以后m行,每行首先有两个数字(x, y),代表了画线的起点坐标,接着用空格隔开一个字符,假如字符是"D ",则是向下连一条边,如果是"R "就是向右连一条边。输入数据不会有重复的边且保证正确。
输出格式
输出一行:在第几步的时候结束。假如m步之后也没有结束,则输出一行“draw”。
样例输入
3 5
1 1 D
1 1 R
1 2 D
2 1 R
2 2 D
样例输出
4
数据范围
思路点拨:
此题如找到方法,即并查集解题。就是Big water。
如题,先判断两点是否在一个并查集中,如是,即已创建出一个圈,如否,把连成线的两点坐标放入并查集,继续下一步操作。
核心代码:
if(k=='D'){//向下画一笔
z=x+1;
int a=x*n+y;
int b=z*n+y;//确定两点坐标
if(FindSet(a)==FindSet(b)){//判断两点是否处于同一并查集。
printf("%d",i);
return 0;
}
else{
UnionSet(a,b);//否,则将两点搞入并查集
}
}
else{//向右画一笔
z=y+1;
int a=x*n+y;
int b=x*n+z;
if(FindSet(a)==FindSet(b)){//判断两点是否处于同一并查集。
printf("%d",i);
return 0;
}
else{
UnionSet(a,b);//同上
}
}
:
#include<bits/stdc++.h>
using namespace std;
int fa[50005];
int n,m;
void MakeSet(int n){
for(int i=1;i<=n;i++){
fa[i]=i;
}
}
int FindSet(int a){
if(fa[a]==a){
return a;
}
else{
return fa[a]=FindSet(fa[a]);
}
}
void UnionSet(int a,int b){
int l=FindSet(a),r=FindSet(b);
if(l==r){
return;
}
else{
fa[r]=l;
}
}
int main(){
scanf("%d%d",&n,&m);
MakeSet((n+1)*(n+1));
for(int i=1;i<=m;i++){
int x,y,z;
char k;
scanf("%d%d %c",&x,&y,&k);
if(k=='D'){
z=x+1;
int a=x*n+y;
int b=z*n+y;
if(FindSet(a)==FindSet(b)){
printf("%d",i);
return 0;
}
else{
UnionSet(a,b);
}
}
else{
z=y+1;
int a=x*n+y;
int b=x*n+z;
if(FindSet(a)==FindSet(b)){
printf("%d",i);
return 0;
}
else{
UnionSet(a,b);
}
}
}
printf("draw");
return 0;
}