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方法都大有裨益, 敬请有兴趣者 ...
随机推荐
- PHP基本连接数据库
最简单的代码 connect.php <?php $host="localhost"; $db_user="root"; $db_pass="& ...
- 假设数组a有n个元素,元素取值范围是1~n,如何判定数组是否存在重复元素
方法一:位图法,原理是首先申请一个长度为n且均为’0’组成的字符串,字符串的下标即为数组a[]中的元素,然后从头开始遍历数组a[N],取每个数组元素的值,将其对应的字符串中的对应位置置1,如果已经置过 ...
- Hibernate_day04讲义_使用Hibernate完成对客户查询的优化
- Java获取项目当前请求的全部URL,Java获取Referer,Java获取完整链接地址URL
Java获取项目当前请求的全部URL,Java获取Referer,Java获取完整链接地址URL >>>>>>>>>>>>> ...
- [XPath] XPath 与 lxml (四)XPath 运算符
XPath 中支持的运算符 # | 或: 返回所有 price 和 title 节点集合 >>> root.xpath('//price|//title') [<Element ...
- 【总结】redis和memcached的区别
1.Redis和Memcache都是将数据存放在内存中,都是内存数据库.不过memcache还可用于缓存其他东西,例如图片.视频等等: 2.Redis不仅仅支持简单的k/v类型的数据,同时还提供lis ...
- Host 'xxx.xx.xxx.xxx' is not allowed to connect to this MySQL server
改表法.可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入mysql后,更改 "mysql" 数据库里的 "use ...
- 【css系列】创建网页加载进度条
一.最简单或者明显的方式是使用定时器 1.在网页中加入布局覆盖真实网页内容 2.使用定时器确定加载所用时间的长短,其实并不是真正的加载进度实现 <!DOCTYPE html> <ht ...
- css笔记 - 张鑫旭css课程笔记之 margin 篇
margin - 人若犯我,我必犯人! [margin地址](https://www.imooc.com/learn/680) 一.margin与容器尺寸的关系 relative可定位,但是不改变容器 ...
- 重载i++,++i操作符
#include <iostream> using namespace std; class Time { public: Time(){min=;sec=;} Time(int m,in ...