ZOJ 3781 - Paint the Grid Reloaded - [DFS连通块缩点建图+BFS求深度][第11届浙江省赛F题]
题目链接: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 <= 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
题意:
两个方格字符一样并且相邻的即为判断为连通,且连通具有传递性;
每次翻转,可以也必须翻转一个连通块的颜色(X→O,O→X),问至少翻转几次可以使得给出的图变得所有方格颜色都一样。
题解:
若把所有连通块缩成一个点看待,那么整个n*m的grid可以变成一个无向二分图;
那么,我们在这个二分图上任取一个点作为出发点,假设这个点在集合L,它沿着一条边走到另一个集合R内的另一个点;
这种沿着一条边走一步的动作,可以看做起点代表的那个连通块翻转了颜色,变成了与终点代表的连通块一样的颜色;
更形象的,相当于该条边的起点并入了终点;
那么我们一直走,就相当于不断地翻转颜色,直到遍历完全部二分图上所有点,就相当于把整个grid都翻成了一个颜色。
那么,翻转次数相当于什么呢?显然就是走过的边数。
显然,我们如果规定好起点,令其深度d[st]=0,那么bfs不断一层层地求其相邻点的d[],
直到全部搜索完,所有d[i]中的最大值,就是以st为起点需要翻转几次才能颜色全部一样。
另外,枚举起点为从(1,1)到(n,m)进行一次dfs就能把所有连通块缩成点,并且建立起一个二分图,这个正确性是可以想见的。
同时,存图方面,本题会卡邻接矩阵,需要使用邻接表。
AC代码:
#include<bits/stdc++.h>
using namespace std; const int INF=0x3f3f3f3f;
const int maxn=;
const int maxm=; 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=;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-);
G[v].push_back(_size-);
} int dr[]={,,,-};
int dc[]={,,-,}; void dfs(int nowr,int nowc,int i)
{
id[nowr][nowc]=i;
for(int k=;k<;k++)
{
int nxtr=nowr+dr[k];
int nxtc=nowc+dc[k]; if(!(<=nxtr && nxtr<=n && <=nxtc && nxtc<=m)) continue;
if(grid[nowr][nowc]==grid[nxtr][nxtc])
{
if(id[nxtr][nxtc]==) dfs(nxtr,nxtc,i);
}
else
{
if(id[nxtr][nxtc]!=)
{
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,,sizeof(vis)); int res=;
queue<int> q;
q.push(st);
vis[st]=;
d[st]=;
while(!q.empty())
{
int u=q.front();q.pop();
res=max(d[u],res);
for(int i=,_size=G[u].size();i<_size;i++)
{
int v=E[G[u][i]].v;
if(vis[v]) continue;
d[v]=d[u]+;
q.push(v);
vis[v]=;
}
} return res;
} int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%s",grid[i]+); //连通块编号 - O(n*m)
init(m*n);
memset(id,,sizeof(id));
int cnt=;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(id[i][j]!=) 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求单源最短路 - O((n*m)^2)
int ans=INF;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
ans=min(bfs(id[i][j],cnt),ans);
}
} printf("%d\n",ans);
}
}
ZOJ 3781 - Paint the Grid Reloaded - [DFS连通块缩点建图+BFS求深度][第11届浙江省赛F题]的更多相关文章
- ZOJ 3781 Paint the Grid Reloaded(BFS+缩点思想)
Paint the Grid Reloaded Time Limit: 2 Seconds Memory Limit: 65536 KB Leo has a grid with N rows ...
- ZOJ 3781 Paint the Grid Reloaded(DFS连通块缩点+BFS求最短路)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5268 题目大意:字符一样并且相邻的即为连通.每次可翻转一个连通块X( ...
- ZOJ 3781 Paint the Grid Reloaded
枚举,$BFS$,连通块缩点. 可以枚举一开始染哪个位置,然后逐层往外染色,看最多需要多少操作次数,也就是算最短距离.连通块缩点之后可以保证是一个黑白相间的图,且每条边的费用均为$1$,$BFS$即可 ...
- ZOJ - 3781 Paint the Grid Reloaded 题解
题目大意: 给一个n*m的X O构成的格子,对一个点操作可以使与它相连通的所有一样颜色的格子翻转颜色(X—>O或O—>X),问给定的矩阵最少操作多少次可以全部变成一样的颜色. 思路: 1. ...
- ZOJ 3781 Paint the Grid Reloaded 连通块
LINK:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3781 题意:n*m只由OX组成的矩阵,可以选择某一连通块变成另一 ...
- ZOJ 3781 Paint the Grid Reloaded(BFS)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3781 Leo has a grid with N rows an ...
- ZOJ 3780 - Paint the Grid Again - [模拟][第11届浙江省赛E题]
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3780 Time Limit: 2 Seconds Me ...
- ZOJ 3777 - Problem Arrangement - [状压DP][第11届浙江省赛B题]
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3777 Time Limit: 2 Seconds Me ...
- 图-用DFS求连通块- UVa 1103和用BFS求最短路-UVa816。
这道题目甚长, 代码也是甚长, 但是思路却不是太难.然而有好多代码实现的细节, 确是十分的巧妙. 对代码阅读能力, 代码理解能力, 代码实现能力, 代码实现技巧, DFS方法都大有裨益, 敬请有兴趣者 ...
随机推荐
- Linux Eclipse 运行Protobuf
安装环境Ubuntu 14.04 64 bit 安装过程分为三步 1. Linux下安装Protobuf 2. Eclipse下安装protobuf.dt插件 3. Eclipse下配置动态链接库并运 ...
- 统计js数组中奇数元素的个数
如何统计一个JS数组中奇数元素的个数呢? 这是群友提出的一个问题,大部分群友给出的是遍历 然后对2取模,得到最终结果. 这样的写法是最容易想得到的,那么有没有其他思路呢? 这里我提供另外一种思路,我们 ...
- ios开发之--[_NSInlineData objectForKeyedSubscript:]
reason: '-[_NSInlineData objectForKeyedSubscript:]: unrecognized selector sent to instance 0x7fa2049 ...
- ios开发之--开发中可能会用到的一些函数
rand() ----随机数 abs() / labs() ----整数绝对值 fabs() / fabsf() / fabsl() ----浮点数绝对值 floor() / floorf() / f ...
- IIS 7安装ModSecurity实现WAF功能
ModSecurity 是一款开源Web应用防火墙,支持Apache/Nginx/IIS,可作为服务器基础安全设施,还是不错的选择. 系统环境:window 2008 R2+IIS 7 0X01 Mo ...
- Steam安装Google Earth VR
打开Steam 打开火狐浏览器 输入steam://install/348250
- PHP之Composer类库依赖管理神器
Composer中文版说明见:https://github.com/kaka987/Composer-zh Composer 是PHP的类包依赖管理工具,用它可以轻松的引用第三方类包,类似于node的 ...
- jQuery事件处理(六)
1.通过一步步调试的的方法观察了一下存放到cache中的事件及其处理程序的数据格式: { events : { // 根据事件类型存放添加到该元素上的所有事件,下面以click为例 click : [ ...
- maven打war包的过程中,都用了哪些插件呢?
一.maven生命周期 http://ifeve.com/introduction-to-the-lifecycle/ https://maven.apache.org/guides/introduc ...
- linux netcat命令使用技巧
netcat是网络工具中的瑞士军刀,它能通过TCP和UDP在网络中读写数据.通过与其他工具结合和重定向,你可以在脚本中以多种方式使用它.使用netcat命令所能完成的事情令人惊讶. netcat所做的 ...