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