1347:【例4-8】格子游戲
時間限制: 1000 ms 內存限制: 65536 KB
提交數: 2734 通過數: 1643
【題目描述】
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
思路: 二維並查集解決的是連通性和傳遞性問題,並且可以動態的維護。任意一個圖中,增加一條邊形成環當且僅當這條邊連接的兩點已經聯通,於是可以將點分爲若干個集合,每個集合對應圖中的一個連通塊。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int n,m,a,b;
char c;
struct node
{
int x,y; //橫縱座標
}father[10001][10001],k1,k2;
node find(node k) //開始找父親
{
if(father[k.x][k.y].x!=k.x&&father[k.x][k.y].y!=k.y) father[k.x][k.y]=find(father[k.x][k.y]);
return father[k.x][k.y];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) //初始化
{
father[i][j].x=i;
father[i][j].y=j;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%s",&a,&b,&c);
if(c=='D') //向下走
{
k1=find(father[a][b]);
k2=find(father[a+1][b]);
}
if(c=='R') //向右走
{
k1=find(father[a][b]);
k2=find(father[a][b+1]);
}
if(k1.x==k2.x&&k1.y==k2.y) //判斷是否連通結束
{
cout<<i<<endl;
return 0;
}
else
father[k1.x][k1.y]=k2; //否則合併
}
cout<<"draw"; //一直未結束
return 0;
}