P10665 [AMPPZ2013] Bytehattan 题解

P10665 [AMPPZ2013] Bytehattan

思路

看到维护网格图(平面图)的连通性,强制在线,想到对偶图。

平面图的对偶图是指对于原图的每一块平面建立一个虚空节点。如果原图中的某条边被删去,那么就会有两个平面被连通。在形式上就是这两个平面对应的虚点间连边。

那如何判定原图上两个点是否连通呢?一个比较显然的观察是如果原图的一个连通块被虚点间的连边“包围” 了,那么这个连通块里的所有点都与这个连通块内的点不连通了。也就是虚点间的连边形成了。可以画个图感受一下。

由于题目要求是删去边后再询问是否连通,因此如果这条边两侧的平面在这条边被删之前就是连通的,那么显然删掉这条边后虚点间的连边就将形成。因此判定是否连通的条件就是删边以前这条边两侧的平面是否已经连通。

点的连通性可以用并查集维护。时间复杂度 \(O(n\alpha)\)。其中 \(\alpha\) 是并查集的复杂度。

code

由于是网格图,因此可以 \(O(1)\) 得到边两侧的平面的序号。如果不是网格图需要预处理。

#include<bits/stdc++.h>
using namespace std;
const int N=2250000+7;
int n,m,fa[N],lst=1,num;
int get(int x,int y){return x<1||y<1||x>=n||y>=n?0:(x-1)*n+y;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int merge(int x,int y){x=find(x),y=find(y);if(x==y)return 0;else {fa[x]=y;return 1;}}
void work(int x,int y,char s){
	if(s=='N'){
		int u=get(x,y),v=get(x-1,y);
		lst=merge(u,v);cout<<(lst?"TAK\n":"NIE\n");
	}
	else{
		int u=get(x,y),v=get(x,y-1);
		lst=merge(u,v);cout<<(lst?"TAK\n":"NIE\n");
	}
}
signed main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>n>>m;num=(n-1)*(n-1)+1;for(int i=0;i<=n*n;i++) fa[i]=i;
	for(int i=1,lx,ly,rx,ry;i<=m;i++){char sl,sr;cin>>lx>>ly>>sl>>rx>>ry>>sr;if(lst)work(lx,ly,sl);else work(rx,ry,sr);}
	return 0;
}
posted @ 2025-05-29 15:08  all_for_god  阅读(17)  评论(0)    收藏  举报