Description
![]() | ![]() | ![]() | ![]() | ![]() |
Figure 1 | Figure 2 | Figure 3a | Figure 3b | Figure 4 |
Your task is to decide if a specified sequence of moves in the board game Twixt ends with a winning move.
In this version of the game, different board sizes may be specified. Pegs are placed on a board at integer coordinates in the range [0, N]. Players Black and White use pegs of their own color. Black always starts and then alternates with White, placing a peg at one unoccupied position (x,y). Black's endzones are where x equals 0 or N, and White's endzones are where y equals 0 or N. Neither player may place a peg in the other player's endzones. After each play the latest position is connected by a segment to every position with a peg of the same color that is a chess knight's move away (2 away in one coordinate and 1 away in the other), provided that a new segment will touch no segment already added, except at an endpoint. Play stops after a winning move, which is when a player's segments complete a connected path between the player's endzones.
For example Figure 1 shows a board with N=4 after the moves (0,2), (2,4), and (4,2). Figure 2 adds the next move (3,2). Figure 3a shows a poor next move of Black to (2,3). Figure 3b shows an alternate move for Black to (2,1) which would win the game.
Figure 4 shows the board with N=7 after Black wins in 11 moves:
(0, 3), (6, 5), (3, 2), (5, 7), (7, 2), (4, 4), (5, 3), (5, 2), (4, 5), (4, 0), (2, 4).
Input
The input contains from 1 to 20 datasets followed by a line containing only two zeroes, "0 0". The first line of each dataset contains the maximum coordinate N and the number of total moves M where 3 < N < 21, 4 < M < 250, and M is odd. The rest of the dataset contains a total of M coordinate pairs, with one or more pairs per line. All numbers on a line will be separated by a space. M being odd means that Black will always be the last player. All data will be legal. There will never be a winning move before the last move.
Output
The output contains one line for each data set: "yes" if the last move is a winning move and "no" otherwise.
Sample Input
4 5 0 2 2 4 4 2 3 2 2 3 4 5 0 2 2 4 4 2 3 2 2 1 7 11 0 3 6 5 3 2 5 7 7 2 4 4 5 3 5 2 4 5 4 0 2 4 0 0
Sample Output
no yes yes
把左右两边看做两个点
最后一步只要点LEFT和RIGHT联通,就输出yes
本题重点在如何判断线是否相交。有人用斜率写的,也可以直接暴力。
/*
因为此题不存在水平线段或者数值线段,所以可以丧心病狂的使用斜率。
设t1,t2为等待被连线的两个点,该线段所在直线斜率为k1,截距为b;
设t3,t4为有可能阻断t1,t2连线的两个点,其所在的斜率亦为k1的直线的截距为b2.b3;
若b,b2,b3满足 (b2 < b < b3) || (b2 > b > b3) 则说明t3,t4所在直线与t1,t2所在直线相交。
然此题是线段,所以还需加限制条件。
*/
一种写法:
bool checkC(int x1,int y1,int x2,int y2)//检查与(x1,y1)相连的点中有木有(x2,y2);
{
for(C *p = head[x1][y1]->next;p != NULL; p = p->next)
{
if(p->x == x2 && p->y == y2)
return true;
}
return false;
}
bool judgeinc(int minx,int maxx,int miny,int maxy,int x,int y,int n)//检查(x,y)是否在黑线所围成的区域内
{
int minx1, maxx1, miny1, maxy1;
minx1 = minx-1 >= 0 ? minx-1 : 0;
maxx1 = maxx+1 <= n ? maxx+1 : n;
miny1 = miny-1 >= 0 ? miny-1 : 0;
maxy1 = maxy+1 <= n ? maxy+1 : n;
int i,j;
for(i = minx1;i <= maxx1; ++i)
{
for(j = miny;j <= maxy; ++j)
{
if(i == x && j == y)
return true;
}
}
for(i = minx;i <= maxx; ++i)
{
for(j = miny1;j <= maxy1; ++j)
{
if(i == x && j == y)
return true;
}
}
return false;
}
bool judgeC(P t1,P t2,int n)//判断两点之间是否有线段阻隔
{
int minx,miny,maxx,maxy;
P temp;
minx = (t1.x < t2.x ? t1.x : t2.x);
maxx = (t1.x > t2.x ? t1.x : t2.x);
miny = (t1.y < t2.y ? t1.y : t2.y);
maxy = (t1.y > t2.y ? t1.y : t2.y);
double k,b,b1,b2;
int i,j,u;
k = (t2.y-t1.y)*1.0/(t2.x-t1.x);
b = t2.y*1.0 - k*t2.x;
//实际上只需要检查与t1,t2在同一 ‘日’ 字内的其余四个点
for(i = minx;i <= maxx; ++i)
{
for(j = miny;j <= maxy; ++j)
{
if( !( (i == t1.x && j == t1.y) || (i == t2.x && j == t2.y) ) )
{
b1 = j*1.0 - k*i;
for(u = 0;u < 8;++u)
{
temp.x = i+jx[u];
temp.y = j+jy[u];
if(0 <= temp.x && temp.y <= n && 0 <= temp.y && temp.y <= n)
{
b2 = temp.y*1.0 - k*temp.x;
if( ( (b1 > b && b > b2) || (b1 < b && b < b2) ) && judgeinc(minx,maxx,miny,maxy,temp.x,temp.y,n) && checkC(i,j,temp.x,temp.y) )
return false;
}
}
}
}
}
return true;
}
一种写法:
void check(int fi,int x1,int y1,int li,int x2,int y2)
{
if(x2<x1)//保证x1<x2,简化情况
{
int t=x1;x1=x2;x2=t;
t=y1;y1=y2;y2=t;
}
if(x1+1==x2)
{
if(y1+2==y2)
{
//1同列的情况
if(v[x1+1][y1+1][x1+1][y2][0])return;
if(v[x1+1][y2][x1+1][y2+1][0])return;
if(v[x1+1][y1][x1+1][y1+1][0])return;
//
if(v[x1][y1+1][x1+1][y1+1][1])return;
if(v[x1][y1+1][x1+1][y1+1][0])return;
if(v[x1+1][y1+1][x1+2][y1+1][0])return;
if(v[x1+1][y1+2][x1+2][y1+2][1])return;
if(v[x1+1][y1+2][x1+2][y1+2][0])return;
if(v[x1][y1+2][x1+1][y1+2][0])return;
v[x1+1][y1+1][x1+1][y1+2][1]=1;
v[x1+1][y1+2][x1+1][y1+1][1]=1;
if(fi%2)
{
fa[find(fi)]=find(li);
}
}
if(y1-2==y2)
{
//0同列的情况
if(v[x1+1][y2+1][x1+1][y2+2][1])return;
if(v[x1+1][y2][x1+1][y2+1][1])return;
if(v[x1+1][y1][x1+1][y1+1][1])return;
//
if(v[x1][y1][x1+1][y1][1])return;
if(v[x1][y1][x1+1][y1][0])return;
if(v[x1+1][y1][x1+2][y1][1])return;
if(v[x1+1][y1-1][x1+2][y1-1][1])return;
if(v[x1+1][y1-1][x1+2][y1-1][0])return;
if(v[x1][y1-1][x1+1][y1-1][1])return;
v[x1+1][y1-1][x1+1][y1][0]=1;
v[x1+1][y1][x1+1][y1-1][0]=1;
if(fi%2)
{
fa[find(fi)]=find(li);
}
}
}
else if(x1+2==x2)
{
if(y1+1==y2)
{
//1
if(v[x1+1][y1+1][x1+2][y1+1][0])return;
if(v[x1][y1+1][x1+1][y1+1][0])return;
if(v[x2][y1+1][x2+1][y1+1][0])return;
//
if(v[x1+1][y1][x1+1][y1+1][1])return;
if(v[x1+1][y1][x1+1][y1+1][0])return;
if(v[x1+1][y1+1][x1+1][y1+2][0])return;
if(v[x2][y2][x2][y2+1][1])return;
if(v[x2][y2][x2][y2+1][0])return;
if(v[x2][y2-1][x2][y2][0])return;
v[x1+1][y1+1][x1+2][y1+1][1]=1;
v[x1+2][y1+1][x1+1][y1+1][1]=1;
if(fi%2)
{
fa[find(fi)]=find(li);
}
}
if(y1-1==y2)
{
//0
if(v[x1+1][y2+1][x1+2][y2+1][1])return;
if(v[x1][y2+1][x1+1][y2+1][1])return;
if(v[x2][y2+1][x2+1][y2+1][1])return;
//
if(v[x1+1][y1][x1+1][y1+1][1])return;
if(v[x1+1][y1][x1+1][y1+1][0])return;
if(v[x1+1][y1-1][x1+1][y1][1])return;
if(v[x2][y2][x2][y2+1][1])return;
if(v[x2][y2][x2][y2+1][0])return;
if(v[x2][y2+1][x2][y2+2][1])return;
v[x1+1][y1][x1+2][y1][0]=1;
v[x1+2][y1][x1+1][y1][0]=1;
if(fi%2)
{
fa[find(fi)]=find(li);
}
}
}
}
void work(int sx,int sy,int id)
{
for(int i=1;i<id;i++)
{
if(i%2==id%2)check(id,sx,sy,i,x[i],y[i]);
}
}
一个大神感天动地的代码:
#include<iostream>
using namespace std;
const int size=23;
const int num=251;
int n; //chess size
int m; //move steps
int lastx,lasty;
int map[size][size]; //对坐标为(x,y)的棋子编号
bool link[num][num]; //标记某两个编号的棋子是否有连线
int posx[]={0,-1,-2,-2,-1,1,2,2,1}; //对应于(x,y)的八个方位
int posy[]={0,2,1,-1,-2,-2,-1,1,2};
typedef class chess
{
public:
int color; //黑棋:1 白棋:0
int r,c;
int connet[8]; //记录与当前棋子直接相连的棋子编号
int pc; //connet的指针
chess()
{
color=-1;
pc=0;
}
}PEG;
void LinePeg(PEG* peg,int i); //把棋子peg[i]与与其相邻的八个方位的同色棋子连线
bool CheckWin(PEG* peg,bool flag); //BFS,检查先手(黑棋)是否把终域连接在一起(赢家)
int main(void)
{
while(cin>>n>>m)
{
if(!n && !m)
break;
memset(map,0,sizeof(map));
memset(link,false,sizeof(link));
PEG* peg=new PEG[m+1];
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
map[x][y]=i; //编号记录
peg[i].r=x;
peg[i].c=y;
if(i%2)
peg[i].color=1; //黑棋
else
peg[i].color=0; //白棋
if(i==m) //记录最后一步棋
{
lastx=x;
lasty=y;
}
LinePeg(peg,i); //把最新下的棋子与其附近的同色棋子相连
}
if(CheckWin(peg,true) && !CheckWin(peg,false))
cout<<"yes"<<endl;
else
cout<<"no"<<endl;
}
return 0;
}
/*把棋子(x,y)与与其相邻的八个方位的同色棋子连线*/
void LinePeg(PEG* peg,int i)
{
int color=peg[i].color;
for(int k=1;k<=8;k++)
{
int r=peg[i].r+posx[k];
int c=peg[i].c+posy[k];
if(r>=0 && r<=n && c>=0 && c<=n) //检查边界
{
if(map[r][c] && peg[ map[r][c] ].color==color) //检查颜色
{
switch(k) //"日"字对角连线
{
case 1: //30度方位
{
if(link[ map[r][c-2] ][ map[r+1][c] ])
break;
if(c-3>=0 && link[ map[r][c-3] ][ map[r+1][c-1] ])
break;
if(c+1<=n && link[ map[r][c-1] ][ map[r+1][c+1] ])
break;
if(r-1>=0)
{
if(link[ map[r-1][c-2] ][ map[r+1][c-1] ])
break;
if(link[ map[r-1][c-1] ][ map[r+1][c] ])
break;
if(link[ map[r-1][c] ][ map[r+1][c-1] ])
break;
}
if(r+2<=n)
{
if(link[ map[r+2][c-2] ][ map[r][c-1] ])
break;
if(link[ map[r+2][c-1] ][ map[r][c-2] ])
break;
if(link[ map[r+2][c] ][ map[r][c-1] ])
break;
}
int a=map[peg[i].r][peg[i].c];
int b=map[r][c];
peg[a].connet[peg[a].pc++]=b;
peg[b].connet[peg[b].pc++]=a;
link[a][b]=link[b][a]=true;
break;
}
case 2: //60度方位
{
if(link[ map[r][c-1] ][ map[r+2][c] ])
break;
if(r-1>=0 && link[ map[r-1][c-1] ][ map[r+1][c] ])
break;
if(r+3<=n && link[ map[r+1][c-1] ][ map[r+3][c] ])
break;
if(c-2>=0)
{
if(link[ map[r][c-2] ][ map[r+1][c] ])
break;
if(link[ map[r+1][c-2] ][ map[r+2][c] ])
break;
if(link[ map[r+2][c-2] ][ map[r+1][c] ])
break;
}
if(c+1<=n)
{
if(link[ map[r][c-1] ][ map[r+1][c+1] ])
break;
if(link[ map[r+1][c-1] ][ map[r][c+1] ])
break;
if(link[ map[r+1][c-1] ][ map[r+2][c+1] ])
break;
}
int a=map[peg[i].r][peg[i].c];
int b=map[r][c];
peg[a].connet[peg[a].pc++]=b;
peg[b].connet[peg[b].pc++]=a;
link[a][b]=link[b][a]=true;
break;
}
case 3: //120度方位
{
if(link[ map[r][c+1] ][ map[r+2][c] ])
break;
if(r-1>=0 && link[ map[r-1][c+1] ][ map[r+1][c] ])
break;
if(r+3<=n && link[ map[r+1][c+1] ][ map[r+3][c] ])
break;
if(c-1>=0)
{
if(link[ map[r][c-1] ][ map[r+1][c+1] ])
break;
if(link[ map[r+1][c-1] ][ map[r][c+1] ])
break;
if(link[ map[r+2][c-1] ][ map[r+1][c+1] ])
break;
}
if(c+2<=n)
{
if(link[ map[r+1][c] ][ map[r][c+2] ])
break;
if(link[ map[r+2][c] ][ map[r+1][c+2] ])
break;
if(link[ map[r+1][c] ][ map[r+2][c+2] ])
break;
}
int a=map[peg[i].r][peg[i].c];
int b=map[r][c];
peg[a].connet[peg[a].pc++]=b;
peg[b].connet[peg[b].pc++]=a;
link[a][b]=link[b][a]=true;
break;
}
case 4: //150度方位
{
if(link[ map[r][c+2] ][ map[r+1][c] ])
break;
if(c-1>=0 && link[ map[r+1][c-1] ][ map[r][c+1] ])
break;
if(c+3<=n && link[ map[r+1][c+1] ][ map[r][c+3] ])
break;
if(r-1>=0)
{
if(link[ map[r-1][c] ][ map[r+1][c+1] ])
break;
if(link[ map[r-1][c+1] ][ map[r+1][c] ])
break;
if(link[ map[r-1][c+2] ][ map[r+1][c+1] ])
break;
}
if(r+2<=n)
{
if(link[ map[r][c+1] ][ map[r+2][c] ])
break;
if(link[ map[r][c+1] ][ map[r+2][c+2] ])
break;
if(link[ map[r][c+2] ][ map[r+2][c+1] ])
break;
}
int a=map[peg[i].r][peg[i].c];
int b=map[r][c];
peg[a].connet[peg[a].pc++]=b;
peg[b].connet[peg[b].pc++]=a;
link[a][b]=link[b][a]=true;
break;
}
case 5: //210度方位
{
if(link[ map[r-1][c] ][ map[r][c+2] ])
break;
if(c-1>=0 && link[ map[r-1][c-1] ][ map[r][c+1] ])
break;
if(c+3<=n && link[ map[r-1][c+1] ][ map[r][c+3] ])
break;
if(r-2>=0)
{
if(link[ map[r-2][c] ][ map[r][c+1] ])
break;
if(link[ map[r-2][c+1] ][ map[r][c+2] ])
break;
if(link[ map[r-2][c+2] ][ map[r][c+1] ])
break;
}
if(r+1<=n)
{
if(link[ map[r][c] ][ map[r-1][c+1] ])
break;
if(link[ map[r+1][c+1] ][ map[r-1][c] ])
break;
if(link[ map[r+1][c+2] ][ map[r-1][c+1] ])
break;
}
int a=map[peg[i].r][peg[i].c];
int b=map[r][c];
peg[a].connet[peg[a].pc++]=b;
peg[b].connet[peg[b].pc++]=a;
link[a][b]=link[b][a]=true;
break;
}
case 6: //240度方位
{
if(link[ map[r-2][c] ][ map[r][c+1] ])
break;
if(r-3>=0 && link[ map[r-3][c] ][ map[r-1][c+1] ])
break;
if(r+1<=n && link[ map[r-1][c] ][ map[r+1][c+1] ])
break;
if(c-1>=0)
{
if(link[ map[r-2][c-1] ][ map[r-1][c+1] ])
break;
if(link[ map[r-1][c-1] ][ map[r][c+1] ])
break;
if(link[ map[r][c-1] ][ map[r-1][c+1] ])
break;
}
if(c+2<=n)
{
if(link[ map[r-1][c] ][ map[r-2][c+2] ])
break;
if(link[ map[r-2][c] ][ map[r-1][c+2] ])
break;
if(link[ map[r-1][c] ][ map[r][c+2] ])
break;
}
int a=map[peg[i].r][peg[i].c];
int b=map[r][c];
peg[a].connet[peg[a].pc++]=b;
peg[b].connet[peg[b].pc++]=a;
link[a][b]=link[b][a]=true;
break;
}
case 7: //300度方位
{
if(link[ map[r-2][c] ][ map[r][c-1] ])
break;
if(r-3>=0 && link[ map[r-3][c] ][ map[r-1][c-1] ])
break;
if(r+1<=n && link[ map[r-1][c] ][ map[r+1][c-1] ])
break;
if(c-2>=0)
{
if(link[ map[r-2][c-2] ][ map[r-1][c] ])
break;
if(link[ map[r-1][c-2] ][ map[r-2][c] ])
break;
if(link[ map[r][c-2] ][ map[r-1][c] ])
break;
}
if(c+1<=n)
{
if(link[ map[r-1][c-1] ][ map[r-2][c+1] ])
break;
if(link[ map[r][c-1] ][ map[r-1][c+1] ])
break;
if(link[ map[r-1][c-1] ][ map[r][c+1] ])
break;
}
int a=map[peg[i].r][peg[i].c];
int b=map[r][c];
peg[a].connet[peg[a].pc++]=b;
peg[b].connet[peg[b].pc++]=a;
link[a][b]=link[b][a]=true;
break;
}
case 8: //330度方位
{
if(link[ map[r][c-2] ][ map[r-1][c] ])
break;
if(c-3>=0 && link[ map[r][c-3] ][ map[r-1][c-1] ])
break;
if(c+1<=n && link[ map[r][c-1] ][ map[r-1][c+1] ])
break;
if(r-2>=0)
{
if(link[ map[r-2][c-2] ][ map[r][c-1] ])
break;
if(link[ map[r-2][c-1] ][ map[r][c-2] ])
break;
if(link[ map[r-2][c] ][ map[r][c-1] ])
break;
}
if(r+1<=n)
{
if(link[ map[r-1][c-1] ][ map[r+1][c-2] ])
break;
if(link[ map[r-1][c-1] ][ map[r+1][c] ])
break;
if(link[ map[r-1][c] ][ map[r+1][c-1] ])
break;
}
int a=map[peg[i].r][peg[i].c];
int b=map[r][c];
peg[a].connet[peg[a].pc++]=b;
peg[b].connet[peg[b].pc++]=a;
link[a][b]=link[b][a]=true;
break;
}
}
}
}
}
return;
}
/*BFS,检查先手(黑棋)是否把终域连接在一起(赢家)*/
bool CheckWin(PEG* peg,bool flag)
{
int NUM;
if(!flag) //通过舍弃最后一步棋,检查最后一步棋是否为决定赢棋的一步
NUM=map[lastx][lasty];
for(int k=0;k<=n;k++)
{
int p=map[0][k];
if(p && p!=NUM && peg[p].color==1)
{
int queue[num];
bool vist[num]={false};
int head=0;
int tail=0;
queue[tail++]=p;
vist[p]=true;
while(head<tail)
{
int s=queue[head++];
if(peg[s].r==n)
return true;
for(int i=0;i<peg[s].pc;i++)
{
int x=peg[s].connet[i];
if(!vist[x])
{
vist[x]=true;
if(!flag && x==NUM)
continue;
queue[tail++]=x;
}
}
}
}
}
return false;
}
代码
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
/*
并查集维护
暴力判边
*/
int n,m,LEFT=0,RIGHT;
int v[25][25][25][25][2];
int x[250+10],y[250+10],fa[250+10];
int find(int x)
{
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
void check(int fi,int x1,int y1,int li,int x2,int y2)
{
if(x2<x1)//保证x1<x2,简化情况
{
int t=x1;x1=x2;x2=t;
t=y1;y1=y2;y2=t;
}
if(x1+1==x2)
{
if(y1+2==y2)
{
//1同列的情况
if(v[x1+1][y1+1][x1+1][y2][0])return;
if(v[x1+1][y2][x1+1][y2+1][0])return;
if(v[x1+1][y1][x1+1][y1+1][0])return;
if(v[x1][y1+1][x1+1][y1+1][1])return;
if(v[x1][y1+1][x1+1][y1+1][0])return;
if(v[x1+1][y1+1][x1+2][y1+1][0])return;
if(v[x1+1][y1+2][x1+2][y1+2][1])return;
if(v[x1+1][y1+2][x1+2][y1+2][0])return;
if(v[x1][y1+2][x1+1][y1+2][0])return;
v[x1+1][y1+1][x1+1][y1+2][1]=1;
v[x1+1][y1+2][x1+1][y1+1][1]=1;
if(fi%2) fa[find(fi)]=find(li);
}
if(y1-2==y2)
{
//0同列的情况
if(v[x1+1][y2+1][x1+1][y2+2][1])return;
if(v[x1+1][y2][x1+1][y2+1][1])return;
if(v[x1+1][y1][x1+1][y1+1][1])return;
if(v[x1][y1][x1+1][y1][1])return;
if(v[x1][y1][x1+1][y1][0])return;
if(v[x1+1][y1][x1+2][y1][1])return;
if(v[x1+1][y1-1][x1+2][y1-1][1])return;
if(v[x1+1][y1-1][x1+2][y1-1][0])return;
if(v[x1][y1-1][x1+1][y1-1][1])return;
v[x1+1][y1-1][x1+1][y1][0]=1;
v[x1+1][y1][x1+1][y1-1][0]=1;
if(fi%2) fa[find(fi)]=find(li);
}
}
else if(x1+2==x2)
{
if(y1+1==y2)
{
//1
if(v[x1+1][y1+1][x1+2][y1+1][0])return;
if(v[x1][y1+1][x1+1][y1+1][0])return;
if(v[x2][y1+1][x2+1][y1+1][0])return;
//
if(v[x1+1][y1][x1+1][y1+1][1])return;
if(v[x1+1][y1][x1+1][y1+1][0])return;
if(v[x1+1][y1+1][x1+1][y1+2][0])return;
if(v[x2][y2][x2][y2+1][1])return;
if(v[x2][y2][x2][y2+1][0])return;
if(v[x2][y2-1][x2][y2][0])return;
v[x1+1][y1+1][x1+2][y1+1][1]=1;
v[x1+2][y1+1][x1+1][y1+1][1]=1;
if(fi%2)
fa[find(fi)]=find(li);
}
if(y1-1==y2)
{
//0
if(v[x1+1][y2+1][x1+2][y2+1][1])return;
if(v[x1][y2+1][x1+1][y2+1][1])return;
if(v[x2][y2+1][x2+1][y2+1][1])return;
//
if(v[x1+1][y1][x1+1][y1+1][1])return;
if(v[x1+1][y1][x1+1][y1+1][0])return;
if(v[x1+1][y1-1][x1+1][y1][1])return;
if(v[x2][y2][x2][y2+1][1])return;
if(v[x2][y2][x2][y2+1][0])return;
if(v[x2][y2+1][x2][y2+2][1])return;
v[x1+1][y1][x1+2][y1][0]=1;
v[x1+2][y1][x1+1][y1][0]=1;
if(fi%2)
fa[find(fi)]=find(li);
}
}
}
void work(int sx,int sy,int id)
{
for(int i=1;i<id;i++)
if(i%2==id%2)
check(id,sx,sy,i,x[i],y[i]);
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
if(n==0&&m==0)break;
memset(v,0,sizeof(v));
for(int i=1;i<=m;i++) fa[i]=i;
fa[LEFT]=LEFT;RIGHT=m+1;fa[RIGHT]=RIGHT;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x[i],&y[i]);
if(i%2)
{
if(x[i]==0)fa[find(i)]=find(LEFT);
if(x[i]==n)fa[find(i)]=find(RIGHT);
}
work(x[i],y[i],i);
}
if(find(LEFT)==find(RIGHT))printf("yes\n");
else printf("no\n");
}
return 0;
}