题目大意:
给定一个网格图,每一次在网格图中间删除一条边,然后询问这条边的两个端点是否连通。
思路:
这是一个平面图,而平面图的判断点的连通与否可以看两个点在对偶图中,中间是否有一个环将它们分为了环外和环内,也就是两个点之间有割。
又因为这两个点是直接相连的,如果这两个点之间有割,那么它们两个直接向连的边是一定在割中的。
于是直接判断这条边割开的这两个区域是否在之前就连通就好了,用并查集维护。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define y1 fuckyou
typedef long long ll;
using namespace std;
void File(){
freopen("bzoj4423.in","r",stdin);
freopen("bzoj4423.out","w",stdout);
}
template<typename T>void read(T &_){
T __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}
const int maxn=1500+10;
int n,m,fa[maxn*maxn];
int find(int x){return fa[x]==x ? x : fa[x]=find(fa[x]);}
bool solve(int x,int y,char ty){
if(ty=='N'){//(a,b) -> (a,b+1)
int u= x==1 ? 0 : (x-2)*(n-1)+y;
int v= x==n ? 0 : (x-1)*(n-1)+y;
if(find(u)==find(v))return 1;
return (fa[find(u)]=find(v),0);
}
else{//(a,b) -> (a+1,b)
int u= y==1 ? 0 : (x-1)*(n-1)+y-1;
int v= y==n ? 0 : (x-1)*(n-1)+y;
if(find(u)==find(v))return 1;
return (fa[find(u)]=find(v),0);
}
}
int main(){
File();
read(n); read(m);
REP(i,0,(n-1)*(n-1))fa[i]=i;
int lasans=0;
int x1,y1,x2,y2;
char s[5],t[5];
REP(i,1,m){
read(x1); read(y1); scanf("%s",s);
read(x2); read(y2); scanf("%s",t);
if(!lasans)lasans=solve(x1,y1,s[0]);
else lasans=solve(x2,y2,t[0]);
printf("%s\n",lasans ? "NIE" : "TAK");
}
return 0;
}