Idea:
record points and add edges during input.
check whether an edge can be added by calculating intersection point of two lines and find out if the intersection point is within the line segments. (see solution())
Since no winning is guatanteed before last point. so after complete input, using dfs to check whether points are connect and cover the whole range of x axis for black player.
// Accepted 312K 16MS
#include<iostream>
#include<vector>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
int N,M;
int dir[8][2]={{-1,2},{-1,-2},{-2,-1},{-2,1},{1,-2},{1,2},{2,-1},{2,1}};
struct Point
{
bool black;//true is black is placed here
bool white;
int x;
int y;
vector<Point> adjp;
int visited;
}P[21][21];
class Edge
{
public:
Point a;
Point b;
int color;//0 for white, 1 for black
};
vector<Edge> vec;
void init()
{
for(int i=0;i<21;i++)
{
for(int j=0;j<21;j++)
{
P[i][j].black=false;
P[i][j].white=false;
P[i][j].adjp.clear();
P[i][j].visited=0;
}
}
}
bool inRange(int x)
{
return x>=0&&x<=N;
}
void solution(float a,float b,float c,float d,float e,float f,float &x1,float &x2)
{
float det=a*d-b*c;
x1=(e*d-b*f)/det;
x2=(a*f-e*c)/det;
}
bool between(float mid,int a,int b)
{
return mid>min(a,b)&&mid<max(a,b);
}
bool intersect(int x,int y,int newx,int newy)
{
for(vector<Edge>::iterator ite=vec.begin();ite!=vec.end();ite++)
{
int x1=P[x][y].x,y1=P[x][y].y,x2=P[newx][newy].x,y2=P[newx][newy].y;
int m1=ite->a.x,n1=ite->a.y,m2=ite->b.x,n2=ite->b.y;
float s1,s2;
solution(y1-y2,x2-x1,n1-n2,m2-m1,-x1*y2+x2*y1,-m1*n2+m2*n1,s1,s2);
//printf("(%d,%d) (%d,%d) (%d,%d) (%d,%d) s1=%f s2=%f bool=%d %d %d %d\n",x1,y1,x2,y2,m1,n1,m2,n2,s1,s2,(int)(between(s1,x1,x2)),(int)(between(s1,m1,m2)),(int)(between(s2,y1,y2)),(int)(between(s2,n1,n2)));
if(between(s1,x1,x2)&&between(s1,m1,m2)&&between(s2,y1,y2)&&between(s2,n1,n2))
{
//printf("x=%d y=%d newx=%d newy=%d intersect=true\n",x,y,newx,newy);
return true;
}
}
//printf("x=%d y=%d newx=%d newy=%d intersect=false\n",x,y,newx,newy);
return false;
}
void dfs(int x,int y,bool &meetleft,bool &meetright)
{
//printf("in dfs x=%d y=%d\n",x,y);
if(x==0)
{
meetleft=true;
}
if(x==N)
{
meetright=true;
}
if(meetleft&&meetright)
{
//cout<<"return in advance"<<endl;
return;
}
for(vector<Point>::iterator ite=P[x][y].adjp.begin();ite!=P[x][y].adjp.end();ite++)
{
if(ite->visited==0)
{
ite->visited=1;
dfs(ite->x,ite->y,meetleft,meetright);
}
}
}
bool complete(int x,int y)
{
bool meetleft=false;
bool meetright=false;
dfs(x,y,meetleft,meetright);
return meetleft&&meetright;
}
int main()
{
//freopen("result.txt","w",stdout);
int x,y;
int newx,newy;
for(int i=0;i<21;i++)
{
for(int j=0;j<21;j++)
{
P[i][j].x=i;
P[i][j].y=j;
}
}
while(1)
{
init();
vec.clear();
scanf("%d%d",&N,&M);
if(N==0&&M==0)
{
break;
}
//bool precondition;
for(int i=0;i<M;i++)
{
scanf("%d%d",&x,&y);
if(i%2==0)//black
{
P[x][y].black=true;
for(int k=0;k<8;k++)
{
newx=x+dir[k][0];
newy=y+dir[k][1];
if(inRange(newx)&&inRange(newy)&&P[newx][newy].black==true)
{
//printf("x=%d y=%d newx=%d newy=%d\n",x,y,newx,newy);
if(!intersect(x,y,newx,newy))
{
Edge e;
e.a=P[x][y];
e.b=P[newx][newy];
e.color=1;
vec.push_back(e);
//printf("x=%d y=%d newx=%d newy=%d is pushed\n",x,y,newx,newy);
P[x][y].adjp.push_back(P[newx][newy]);
P[newx][newy].adjp.push_back(P[x][y]);
//printf("x=%d y=%d connect newx=%d newy=%d\n",x,y,newx,newy);
}
}
}
if(i==M-1)
{
cout<<((complete(x,y))? "yes" : "no")<<endl;
}
}
else
{
P[x][y].white=true;
for(int k=0;k<8;k++)
{
newx=x+dir[k][0];
newy=y+dir[k][1];
if(inRange(newx)&&inRange(newy)&&P[newx][newy].white==true)
{
if(!intersect(x,y,newx,newy))
{
Edge e;
e.a=P[x][y];
e.b=P[newx][newy];
e.color=0;
vec.push_back(e);
//printf("x=%d y=%d newx=%d newy=%d (white)is pushed\n",x,y,newx,newy);
}
}
}
}
}
}
}