[bzoj4423][AMPPZ2013]Bytehattan——对偶图+并查集 大佬们的博客 Some Links

版权声明:欢迎大家转载,转载请标明出处。 https://blog.csdn.net/ylsoi/article/details/82852348

题目大意:

给定一个网格图,每一次在网格图中间删除一条边,然后询问这条边的两个端点是否连通。

思路:

这是一个平面图,而平面图的判断点的连通与否可以看两个点在对偶图中,中间是否有一个环将它们分为了环外和环内,也就是两个点之间有割。
又因为这两个点是直接相连的,如果这两个点之间有割,那么它们两个直接向连的边是一定在割中的。
于是直接判断这条边割开的这两个区域是否在之前就连通就好了,用并查集维护。

#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;
}

猜你喜欢

转载自blog.csdn.net/ylsoi/article/details/82852348