ZOJ 3781 Paint the Grid Reloaded BFS

题意:

给定n*m 的矩阵

每个格子有O X 两种颜色

可以选择1个同颜色的块,翻转为另一个颜色。

问翻转为只有1种颜色需要最小几次操作

bfs枚举每个第一次选择的节点


#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define N 45
#define inf 100000000
int n,m;
char mp[N][N];
int Hash(int x, int y){return x*m+y;}
int f[N*N],F[N][N];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void Union(int x,int y){
	int fx = find(x), fy = find(y);
	if(fx<fy)swap(fx,fy);
	f[fx] = fy;
}

vector<int>G[N*N];
void ADD(){
	for(int i = 0; i < n; i++)
		for(int j = 0; j < m; j++)
		{
			if(i-1>=0 && F[i-1][j] != F[i][j])G[F[i-1][j]].push_back(F[i][j]), G[F[i][j]].push_back(F[i-1][j]);
			if(j-1>=0 && F[i][j-1] != F[i][j])G[F[i][j-1]].push_back(F[i][j]), G[F[i][j]].push_back(F[i][j-1]);
		}
		for(int i = 0; i < n*n; i++){
			sort(G[i].begin(), G[i].end());
			G[i].resize(unique(G[i].begin(), G[i].end())-G[i].begin());
		}
}
int vis[N*N];
int bfs(int u){
	int ans = 0;
	memset(vis, -1, sizeof vis);
	queue<int>q; q.push(u); vis[u] = 0;
	while(!q.empty()){
		int u = q.front(); q.pop();
		ans = max(ans, vis[u]);
		for(int i = 0; i < G[u].size(); i++){
			int v = G[u][i]; if(vis[v]!=-1)continue;
			vis[v] = vis[u]+1;
			q.push(v);
		}
	}
	return ans;
}

set<int>myset;
void init(){myset.clear();for(int i = 0; i <= n*m; i++)f[i] = i ,G[i].clear();}
int main(){
	int T;scanf("%d",&T);
	int i, j;
	while(T--){
		scanf("%d %d",&n,&m);
		init();
		for(i = 0; i < n; i++)scanf("%s",mp[i]);
		for(i = 0; i < n; i++)
		{
			for(j = 0; j < m; j++)
			{
				int now = Hash(i,j);
				int a = Hash(i,j-1), b = Hash(i-1,j);
				if(i-1>=0 && mp[i-1][j] == mp[i][j])Union(now,b);
				if(j-1>=0 && mp[i][j-1] == mp[i][j])Union(now,a);
			}
		}
		for(i = 0; i < n*m; i++)find(i);
		for(i = 0; i < n*m; i++)myset.insert(f[i]);
		//	for(set<int>::iterator p=myset.begin(); p != myset.end(); p++)G[n*n].push_back(*p);
		for(i = 0; i < n; i++)for(j = 0; j < m; j++)F[i][j] = f[Hash(i,j)];
		ADD();
		int A = inf;
		for(set<int>::iterator p=myset.begin(); p != myset.end(); p++)
			A = min(A, bfs(*p));
		printf("%d\n",A);
	}
	return 0;
}


你可能感兴趣的:(ZOJ 3781 Paint the Grid Reloaded BFS)