现在的位置: 首页 > 算法 > 正文

zoj 3781 Paint the Grid Reloaded 最短路变形

2019年02月19日 算法 ⁄ 共 2446字 ⁄ 字号 评论关闭

题意:给出n*m的只包含‘X’或‘O’的矩阵,可以将一个联通块内所有相连的X翻转成O,也可以将相连的O翻转成X,(相连指有一边相连)问翻转到同一种字符的最少次数

将联通块缩点,然后到别的联通块的距离就是翻转到该联通块需要的次数,对以每个联通块为起点跑一次最短路,求出最长距离,然后在最长距离里面找最短的就行了

/*************************************************************************
    > File Name: a.cpp
    > Author: zzx
    > Mail: 1640787991@qq.com 
    > Created Time: 2015年03月11日 星期三 21时09分13秒
 ************************************************************************/

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 45;

char a[N][N];
int mat[N][N];
bool vis[N][N];
int c[N*N];
int n, m;
int cnt;
int dir[4][2] = {
	1, 0, -1, 0, 0, 1, 0, -1
};
int usd[N * N];
int dis[N*N];

struct edge{
	int v, nxt, w;
}e[N*N*N*N];
int head[N*N];
int k;

queue <int> q;

void init()
{
	memset( vis, 0, sizeof ( vis ) );
	memset( mat, 0, sizeof ( mat ) );
	memset( c, 0, sizeof( c ) );
	k = 0;
	memset( head, -1, sizeof( head ) );
}

void add( int u, int v, int w )
{
	e[k].v = v;
	e[k].w = w;
	e[k].nxt = head[u];
	head[u] = k++;

	e[k].v = u;
	e[k].w = w;
	e[k].nxt = head[v];
	head[v] = k++;
}

void dfs( int x, int y, char col )
{
	for( int i = 0; i < 4; ++i )
	{
		int xx = x + dir[i][0];
		int yy = y + dir[i][1];
		if( vis[xx][yy] && a[xx][yy] != col )
		{
			add( mat[xx][yy], mat[x][y], 1 );
			//printf("u: %d v: %d\n", mat[x][y], mat[xx][yy] );
			continue;
		}
		if( !vis[xx][yy] && xx >= 1 && xx <= n && yy >= 1 && yy <= m && a[xx][yy] == col )
		{
			vis[xx][yy] = 1;
			mat[xx][yy] = cnt;
			dfs( xx, yy, col );
		}
	}
}

int spfa( int x, int y )
{
	int st = mat[x][y];
	memset( usd, 0, sizeof( usd ) );
	memset( dis, inf, sizeof( dis ) );
	while( !q.empty( ) )
		q.pop();
	dis[ st ] = 0;
	usd[ st ] = 1;
	int res = -1;
	q.push(st);
	while( !q.empty( ) )
	{
		int u = q.front();
		q.pop();
		usd[u] = 0;
		for( int i = head[u]; ~i; i = e[i].nxt )
		{
			int v = e[i].v;
			//printf("u: %d v: %d\n", u, v);
			if( dis[v] > dis[u] + e[i].w )
			{
				dis[v] = dis[u] + e[i].w;
				if( !usd[v] )
				{
					usd[v] = 1;
					q.push( v );
				}
			}
		}
	}
	for( int i = 1; i <= n*m; ++i )
		if( dis[i] != inf && i != st )
			res = max( res, dis[i] );
	//printf("res: %d\n", res);
	return res;
}

int main()
{
	int tot;
	scanf("%d", &tot);
	while( tot-- )
	{
		init();
		cnt = 0;
		scanf("%d%d", &n, &m);
		for( int i = 1; i <= n; i++ )
			scanf("%s", a[i] + 1);
		for( int i = 1; i <= n; i++ )
		{
			for( int j = 1; j <= m; ++j )
			{
				if( !vis[i][j] )
				{
					vis[i][j] = 1;
					mat[i][j] = ++cnt;
					char col = a[i][j];
					dfs( i, j, col );
				}
			}
		}
		if( cnt == 1 )
		{
			puts("0");
			continue;
		}
		else if( cnt == 2 )
		{
			puts("1");
			continue;
		}
		/*
		for( int i = 1; i <= n; ++i )
		{
			for( int j = 1; j <= m; ++j )
				printf("%d ", mat[i][j]);
			puts("");
		}
		*/
		int ans = inf;
		for( int i = 1; i <= n; ++i )
		{
			for( int j = 1; j <= m; ++j )
			{
				if( !c[ mat[i][j] ] )
				{
					c[ mat[i][j] ] = 1;
					ans = min( ans, spfa( i, j ) );
				}
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

/*
2
3 6
OOXOOX
XOXOOX
XXOXOO
2
*/

抱歉!评论已关闭.