ZOJ 3781 - Paint the Grid Reloaded - [DFS Connected Block Condensation Map + BFS for Depth] [The 11th Zhejiang Provincial Competition F Question]

Topic link: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3781

Time Limit: 2 Seconds      Memory Limit: 65536 KB

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 <= NM <= 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

 

Title:

Two square characters that are the same and adjacent to each other are judged to be connected, and the connection is transitive;

For each flip, the color of a connected block can and must be flipped (X→O, O→X), and at least several flips can make the given graph become the same color for all squares.

 

answer:

If all connected blocks are reduced to one point, then the entire n*m ​​grid can be turned into an undirected bipartite graph;

Then, we take any point on this bipartite graph as the starting point, assuming that this point is in the set L, it goes along an edge to another point in another set R;

This action of taking one step along an edge can be seen as the connected block represented by the starting point flips the color and becomes the same color as the connected block represented by the end point;

More vividly, it is equivalent to the start point of the edge merged into the end point;

Then we keep walking, which is equivalent to flipping the color continuously until we traverse all the points on the complete bipartite graph, which is equivalent to flipping the entire grid into one color.

So, what is the equivalent of flip count? Obviously it's the number of edges traveled.

Obviously, if we specify the starting point and make its depth d[st]=0, then bfs continuously finds the d[] of its adjacent points layer by layer,

Until all searches are completed, the maximum value in all d[i], that is, starting from st, needs to be flipped several times to make the colors all the same.

 

AC code:

#include<bits/stdc++.h>
using namespace std;

const  int INF = 0x3f3f3f3f ;
const  int maxn = 43 ;
const  int maxm = 43 ;

int n,m;
char grid[maxn][maxm]; //存储grid
int id[maxn][maxm];

struct Edge{
    int u,v;
    Edge(int u,int v){this->u=u,this->v=v;}
};
vector<Edge> E;
vector<int> G[maxn*maxm];
void init(int n)
{
    E.clear();
    for(int i=0;i<=n;i++) G[i].clear();
}
void addedge(int u,int v)
{
    E.push_back(Edge(u,v));
    E.push_back(Edge(v,u));
    int _size=E.size();
    G[u].push_back(_size-2);
    G[v].push_back(_size-1);
}

int dr[4]={0,1,0,-1};
int dc[4]={1,0,-1,0};

void dfs(int nowr,int nowc,int i)
{
    id[nowr][nowc]=i;
    for(int k=0;k<4;k++)
    {
        int nxtr=nowr+dr[k];
        int nxtc=nowc+dc[k];

        if(!(1<=nxtr && nxtr<=n && 1<=nxtc && nxtc<=m)) continue;
        if(grid[nowr][nowc]==grid[nxtr][nxtc])
        {
            if(id[nxtr][nxtc]==0) dfs(nxtr,nxtc,i);
        }
        else
        {
            if(id[nxtr][nxtc]!=0)
            {
                int idnow=id[nowr][nowc], idnxt=id[nxtr][nxtc];
                addedge(idnow,idnxt);
            }
        }
    }
}

int d [maxn * maxm];
bool vis [maxn * maxm];
int bfs ( int st, int cnt)
{
    memset(vis,0,sizeof(vis));

    int res=0;
    queue<int> q;
    q.push(st);
    vis [st] = 1 ;
    d[st]=0;
    while(!q.empty())
    {
        int u=q.front();q.pop();
        res=max(d[u],res);
        for(int i=0,_size=G[u].size();i<_size;i++)
        {
            int v=E[G[u][i]].v;
            if(vis[v]) continue;
            d[v]=d[u]+1;
            q.push(v);
            force[v] = 1 ;
        }
    }

    return res;
}

intmain ()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%s",grid[i]+1);

        // Connected block number - O(n*m) 
        init(m* n);
        memset(id,0,sizeof(id));
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(id[i][j]!=0) continue;
                dfs(i,j,++cnt);
            }
        }

        //for(int i=1;i<=cnt;i++) {for(int j=1;j<=cnt;j++) printf("%d ",edge[i][j]); printf("\n");}

        // SPFA find single source shortest path - O((n*m)^2) 
        int ans= INF;
         for ( int i= 1 ;i<=n;i++ )
        {
            for(int j=1;j<=m;j++)
            {
                years = min(bfs(id[i][j],cnt),years);
            }
        }

        printf("%d\n",ans);
    }
}

Guess you like

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