P5877 棋盘游戏(二维并查集转化为一维!!!)

思路:

求连通块数量,首先想到二维并查集

与其它并查集不同,在棋盘上需要二维并查集,用一维数组fa记录每个坐标的祖先,用二维数组记录每个点的颜色。(1表示白点,2表示黑点)

二维并查集一般采用压缩成一维的方法,将坐标为(x,y)的点记录为 (x−1)×m+y ,m 为一行中点的数量(此题中为 n,棋盘是 n×n 的),这样就可以存储祖先了。

由于我从 11~n 存储点,数组开的略大,所以没有判断边界,然后新加一个点 ans++,连通块合并时 ans - - 即可。

使用并查集一定要初始化,最好也要路径压缩(没试过,不知道会不会T),每次修改直接将一个连通块的祖先并到另一个祖先。(就是敲一个并查集板子)

ACcode:


#include
using namespace std;
#define int long long
const int N=5e2+10;
int n,m,a[N][N],fa[N*N];//二维并查集优化为一维 
int idx[]= {0,0,1,-1},idy[]= {1,-1,0,0};
int find(int x) {//并查集 
	return fa[x]==x?x:fa[x]=find(fa[x]);
}
void solve() {
	memset(a,-1,sizeof a);
	cin>>n>>m;
	for(int i=1; i<=n*n; i++) fa[i]=i;//并查集初始化父节点 
	int ans=0;
	while(m--) {
		int c,x,y;
		cin>>c>>x>>y;
		a[x][y]=c;
		ans++;
		for(int i=0; i<4; i++) {
			int xx=x+idx[i];
			int yy=y+idy[i];
			if(xx<1||xx>n||yy<1||yy>n||a[xx][yy]!=a[x][y])continue;
			int f1=find((x-1)*n+y);
			int f2=find((xx-1)*n+yy);
			if(f1!=f2) {
				fa[f1]=f2;
				ans--;
			}
		}
		cout<>tt;
	while(tt--) solve();
	return 0;
}
//3

over~

你可能感兴趣的:(算法,并查集)