二维并查集 例4-8】格子游戏

例4-8】格子游戏


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 254     通过数: 149 

【题目描述】

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

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

二维并查集 例4-8】格子游戏_第1张图片

直到围成一个封闭的圈(面积不必为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

【分析】


如果起点在集合里,终点也在集合里,那么符合条件,输出当时的步数就可以了;如果不符合上面的条件,把点入集合;如果到最后还没有符合条件的情况,输出draw就可以了。

【代码实现】


#include
using namespace std;
#define N 400
struct node
{
    int x,y;
}f[N][N],n1,n2;
int n,m;
node root(node k)
{
  if(k.x==f[k.x][k.y].x&&k.y==f[k.x][k.y].y)
        return k;
  f[k.x][k.y]=root(f[k.x][k.y]);
  return f[k.x][k.y];
}
int main()
{
   int x,y;
   char ch;
   scanf("%d%d",&n,&m);
   for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
   {
       f[i][j].x=i;
       f[i][j].y=j;
   }
   for(int i=1;i<=m;i++)
   {
       scanf("%d%d",&x,&y);
  cin.get();
       cin>>ch;
       if(ch=='D')
       {
        n1=root(f[x][y]);
        n2=root(f[x+1][y]);
       }
       if(ch=='R')
       {
           n1=root(f[x][y]);
          n2=root(f[x][y+1]);
       }
       if (n1.x==n2.x&&n1.y==n2.y)
        {
            printf("%d\n",i);
            return 0;
        }
        else
            f[n1.x][n1.y]=n2;
   }
   printf("draw\n");
   return 0;
}

你可能感兴趣的:(图论——并查集)