ZOJ3781 Paint the Grid Reloaded(dfs,bfs,connected block shrink point)

describe

Leo has a grid with N rows and M columns. All cells are painted with
either black or white initially.

Two cells A and B are called connected if they share an edge and they
are in the same color, or there exists a cell C connected to both A
and B.

Leo wants to paint the grid with the same color. He can make it done
in multiple steps. At each step Leo can choose a cell and flip the
color (from black to white or from white to black) of all cells
connected to it. Leo wants to know the minimum number of steps he
needs to make all cells in the same color.

Input

There are multiple test cases. The first line of input contains an
integer T indicating the number of test cases. For each test case:

The first line contains two integers N and M (1 <= N, M <= 40). Then N
lines follow. Each line contains a string with N characters. Each
character is either ‘X’ (black) or ‘O’ (white) indicates the initial
color of the cells.

Output

For each test case, output the minimum steps needed to make all cells
in the same color.

Sample Input

2
2 2
OX
OX
3 3
XOX
OXO
XOX

Sample Output

1
2

Hint

For the second sample, one optimal solution is:

Step 1. flip (2, 2)

XOX OOO XOX Step 2. flip (1, 2)

XXX XXX XXX

ideas

Let’s talk about the meaning of the question first, give a n*mpicture with two patterns in it, Xand O, now you can choose a point at a time, and then you can change the connected block of the same color where this point is located to the opposite color, ask the minimum number of operations Second, the color of this matrix can be made the same.

First, we can map each connected block, assuming the given graph is like this:


Then after the transformation, it will become:

the graph comes from the network, 1~5there should be an edge, and the author of the graph forgot to draw it.

Because we are mapping connected blocks, we can guarantee that every two points represent different colors. When we start from a point on the graph, all the edges connected by this point must be of opposite colors, so the number of operations from this point to all the edges connected to it should be 1, because they can definitely form a connection Blocks, for example, the points on the graph start from 0, and 0 is connected to two points 1 and 3, then these three points 0, 1, and 3 can become the same color through one operation, so we only need From each point BFS, how many operations need to be processed can make the whole graph into a fast connection, and then find the smallest from these maximum values ​​is the answer

code

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include<list>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 999999999
typedef long long ll;
const int N=50;
int n,m;
int num[N][N];
char s[N][N];
int go[4][2]= {1,0,-1,0,0,1,0,-1};
int first[N*N],tot,cnt;
int vis[4*N*N];
struct edge
{
    int v,next;
} e[2*4*N*N];
void add_edge(int u,int v)
{
    e[tot].v=v;
    e[tot].next=first[u];
    first[u]=tot++;
}
void init()
{
    mem(num,-1);
    mem(first,-1);
    tot=0;
    cnt=0;
}
void dfs(int x,int y,int ct,char ch)
{
    for(int i=0; i<4; i++)
    {
        int xx=x+go[i][0];
        int yy=y+go[i][1];
        if(xx>=0&&xx<n&&yy>=0&&yy<=m)
        {
            if(s[xx][yy]==ch)
            {
                if(num[xx][yy]==-1)
                {
                    num[xx][yy]=ct;
                    dfs(xx,yy,ct,ch);
                }
            }
            else if(num[xx][yy]!=-1)
            {
                int u=ct,v=num[xx][yy];
                add_edge(u,v);
                add_edge(v,u);
            }
        }
    }
}
struct node
{
    int x,step;
};
int bfs(int x)
{
    mem(vis,0);
    vis[x]=1;
    int maxx=0;
    queue<node>q;
    node now,to;
    now.x=x,now.step=0;
    q.push(now);
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        maxx=max(maxx,now.step);
        int u=now.x;
        to.step=now.step+1;
        for(int i=first[u]; ~i; i=e[i].next)
        {
            int v=e[i].v;
            if(!vis[v])
            {
                vis[v]=1;
                to.x=v;
                q.push(to);
            }
        }
    }
    return maxx;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init();
        for(int i=0; i<n; i++)
            scanf("%s",s[i]);
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                if(num[i][j]==-1)
                {
                    num[i][j]=cnt++;
                    dfs(i,j,cnt-1,s[i][j]);
                }
        int ans=inf;
        for(int i=0; i<cnt; i++)
        {
            int maxx=bfs(i);
            ans=min(ans,maxx);
        }
        printf("%d\n",ans);
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324826870&siteId=291194637