【bzoj4423】[AMPPZ2013]Bytehattan 对偶图+并查集

题目描述

比特哈顿镇有n*n个格点,形成了一个网格图。一开始整张图是完整的。
有k次操作,每次会删掉图中的一条边(u,v),你需要回答在删除这条边之后u和v是否仍然连通。

输入

第一行包含两个正整数n,k(2<=n<=1500,1<=k<=2n(n-1)),表示网格图的大小以及操作的个数。
接下来k行,每行包含两条信息,每条信息包含两个正整数a,b(1<=a,b<=n)以及一个字符c(c=N或者E)。
如果c=N,表示删除(a,b)到(a,b+1)这条边;如果c=E,表示删除(a,b)到(a+1,b)这条边。
数据进行了加密,对于每个操作,如果上一个询问回答为TAK或者这是第一个操作,那么只考虑第一条信息,否则只考虑第二条信息。
数据保证每条边最多被删除一次。

输出

输出k行,对于每个询问,如果仍然连通,输出TAK,否则输出NIE。

样例输入

3 4
2 1 E 1 2 N
2 1 N 1 1 N
3 1 N 2 1 N
2 2 N 1 1 N

样例输出

TAK
TAK
NIE
NIE


题解

对偶图+并查集

由于强制在线,不能时光倒流+加边。

考虑对偶图。

对于每条线段挨着的两个面积块,如果它们之间是连通的,

则删除这条线段后这两个面积块会在一个环中,且这个环包含且只包含两个端点中的一个(即一个点在环里,一个点在环外),不能连通。

反过来也成立。

所以只需要把平面图删边转化为对偶图加边就可以了。

然后用并查集维护一下连通性即可。

#include <cstdio>
int f[2250010] , id[1510][1510];
char str[5];
int find(int x)
{
	return x == f[x] ? x : f[x] = find(f[x]);
}
int main()
{
	int n , k , i , j , a , b , x , y , tx , ty , last = 0;
	scanf("%d%d" , &n , &k);
	n -- ;
	for(i = 1 ; i <= n ; i ++ )
		id[0][i] = id[i][n + 1] = id[i][0] = id[n + 1][i] = 0;
	for(i = 1 ; i <= n ; i ++ )
		for(j = 1 ; j <= n ; j ++ )
			id[i][j] = (i - 1) * n + j;
	for(i = 0 ; i <= n * n ; i ++ )
		f[i] = i;
	while(k -- )
	{
		if(last) scanf("%*d%*d%*s%d%d%s" , &a , &b , str);
		else scanf("%d%d%s%*d%*d%*s" , &a , &b , str);
		if(str[0] == 'N') x = id[a - 1][b];
		else x = id[a][b - 1];
		y = id[a][b];
		tx = find(x) , ty = find(y);
		if(tx != ty) puts("TAK") , last = 0;
		else puts("NIE") , last = 1;
		f[tx] = ty;
	}
	return 0;
}

 

posted @ 2017-03-09 18:57  GXZlegend  阅读(398)  评论(0编辑  收藏  举报