简单环路

题目描述

有一个N x M 大小的地图,地图中的每个单元包含一个大写字母。
若两个相邻的(这里的相邻指“上下左右”相邻)点上的字母相同,我们可以用线段连接这两个点。
若存在一个包含同一字母的环路,那么连接这些点我们可以得到一个多边形,
当且仅当多边形的边数大于等于4时,我们称这幅地图中存在“简单环路”。
现在给你一份地图,你来判断是否存在“简单环路”。
列如:
3 4
AAAA
ABCA
AAAA
字符“A”可以构成一个“简单环路”,其边数为4。

输入

第一行输入两个正整数n,m,2<=n,m<=50,分别表示地图的行列数。
接下来输入n行,每行m个大写字母。

输出

若存在“简单环路”输出“Yes”,否则输出“No”。

样例输入

复制
3 4
AAAA
ABCA
AADA

样例输出

复制
No

大致分析:

  要想存在一个多边形,至少需要四条边,因为只能上下左右移动。

  方法1:重新构图——把每个字母当成一个点,判断上下左右如果有相同的则连上一条边。用tarjan算法来进行判环,若遇见连接到更小的搜索序号dfn[]时,则可以认为这时找到了一个环,然后把这个环弹出来,数数长度(看是否满足要求),再逆序放回去。

方法2:据说搜索就可以了,只有相同字符之间的才可以进行搜索;后台数据比较弱,我用错误的代码都过了。


答案:

  

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include<math.h>
#include <string.h>
#include<set>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 10000000
const double pi=acos(-1.0);
#define ll long long
#define N 55
#define M 50*50+5
char a[][];
vector<int>G[M];//表示每个点的周围四个点的情况
int low_link[M],dfn[M],inst[M];
int Time;
int dir[][]={{,},{,-},{,},{-,} };
int n,m;
bool flag;
stack<int>st;
void judge(int i,int j,int num){
for(int k=;k<=;k++){
int dx=i+dir[k][];
int dy=j+dir[k][];
if(dx>=&&dx<=n-&&dy>=&&dy<=m-&&a[dx][dy]==a[i][j]){
G[num].push_back(dx*m+dy);
}
}
}
void init(){
Time=;
flag=false;
for(int i=;i<=n*m;i++)
G[i].clear();
memset(low_link,,sizeof(low_link));
memset(dfn,,sizeof(dfn));
memset(inst,,sizeof(inst));
while(!st.empty())
st.pop();
}
void tarjan(int u,int fa){
low_link[u]=dfn[u]=++Time;
st.push(u);
inst[u]=;
for(int i=;i<(int)G[u].size();i++){
int v=G[u][i];
if(!dfn[v]){
tarjan(v,u);
low_link[u]=min(low_link[u],low_link[v]);
}
else if(inst[v]==&&v!=fa){
low_link[u]=min(low_link[u],dfn[v]);
stack<int>q;
int cnt=;
while(st.top()!=v){
q.push(st.top());
st.pop();
cnt++;
}
if(cnt>=){
flag=true;
// printf("u=%d v=%d\n",u,v);
}
while(q.size()>){
st.push(q.top());q.pop();
}
}
} if(low_link[u]==dfn[u]){
while(st.top()!=u){
// printf("u=%d %d\n",u,st.top());
inst[st.top()]=;st.pop();
}
inst[st.top()]=;st.pop(); } }
void debug(){
for(int i=;i<n;i++){
for(int j=;j<m;j++){
int num=i*m+j;
for(int v=;v<G[num].size();v++){
printf("%d:%d ",num,G[num][v]);
}
cout<<endl;
}
}
}
int main(){ while(scanf("%d%d",&n,&m)!=EOF){
init();
for(int i=;i<n;i++)
scanf("%s",a[i]);
for(int i=;i<n;i++){
for(int j=;j<m;j++){
int num=i*m+j;
judge(i,j,num);
}
}
// debug();
for(int i=;!flag&&i<n;i++){
for(int j=;!flag&&j<m;j++){
int num=i*m+j;
if(!dfn[num]){
tarjan(num,-);
//if(flag==true)
// printf("Yes num=%d\n",num);
}
}
}
if(flag==true)
printf("Yes\n");
else
printf("No\n");
} return ;
}

  

【搜索/tarjan找环】zznu-简单环路的更多相关文章

  1. POJ 2553 The Bottom of a Graph Tarjan找环缩点(题解解释输入)

    Description We will use the following (standard) definitions from graph theory. Let V be a nonempty ...

  2. 【简易DFS/BFS+标记搜索次序的数组】zznu-2025 : 简单环路

    2025 : 简单环路 时间限制:1 Sec 内存限制:128 MiB提交:145 答案正确:41 提交 状态 编辑 讨论区 题目描述 有一个N x M 大小的地图,地图中的每个单元包含一个大写字母. ...

  3. 洛谷 2921 记忆化搜索 tarjan 基环外向树

    洛谷 2921 记忆化搜索 tarjan 传送门 (https://www.luogu.org/problem/show?pid=2921) 做这题的经历有点玄学,,起因是某个random题的同学突然 ...

  4. zstu.4191: 无向图找环(dfs树 + 邻接表)

    4191: 无向图找环 Time Limit: 5 Sec  Memory Limit: 128 MB Submit: 117  Solved: 34 Description 给你一副无向图,每条边有 ...

  5. HDU - 6370 Werewolf 2018 Multi-University Training Contest 6 (DFS找环)

    求确定身份的人的个数. 只能确定狼的身份,因为只能找到谁说了谎.但一个人是否是民,无法确定. 将人视作点,指认关系视作边,有狼边和民边两种边. 确定狼的方法只有两种: 1. 在一个仅由一条狼边组成的环 ...

  6. 【2019.7.16 NOIP模拟赛 T1】洗牌(shuffle)(找环)

    找环 考虑每次洗牌其实是一次置换的过程,而这样必然就会有循环出现. 因此我们直接通过枚举找出每一个循环,询问时只要找到环上对应的位置就可以了. 貌似比我比赛时被卡成\(30\)分的倍增简单多了? 代码 ...

  7. CodeForces 711D Directed Roads (DFS找环+组合数)

    <题目链接> 题目大意: 给定一个$n$条边,$n$个点的图,每个点只有一条出边(初始状态),现在能够任意对图上的边进行翻转,问你能够使得该有向图不出先环的方案数有多少种. 解题分析: 很 ...

  8. 与图论的邂逅06:dfs找环

    当我在准备做基环树的题时,经常有了正解的思路确发现不会找环,,,,,,因为我实在太蒻了. 所以我准备梳理一下找环的方法: 有向图 先维护一个栈,把遍历到的节点一个个地入栈.当我们从一个节点x回溯时无非 ...

  9. Mouse Hunt CodeForces - 1027D(思维 找环)

    Medicine faculty of Berland State University has just finished their admission campaign. As usual, a ...

随机推荐

  1. robot:截图关键字

    参考: https://www.cnblogs.com/hong-fithing/p/9656221.html--python https://blog.csdn.net/weixin_4315628 ...

  2. css 修改placeholder样式

    input::-webkit-input-placeholder{ color:red; } input::-moz-placeholder{ /* Mozilla Firefox 19+ */ co ...

  3. idea更换项目取消直接在当前窗口打开,设置为询问

  4. python openpyxl模块实现excel的读取,新表创建及原数据表追加新数据

    当实际工作需要把excel表的数据读取出来,或者把一些统计数据写入excel表中时,一个设计丰富,文档便于寻找的模块就会显得特别的有吸引力,本文对openpyxl模块的一些常见用法做一些记录,方便工作 ...

  5. Zuul【限流】

    在项目中,大部分都会使用到hyrtrix做熔断机制,通过某个预定的阈值来对异常流量进行降级处理,除了做服务降级以外,还可以对服务进行限流,分流,排队等. 当然,zuul也能做到限流策略,最简单的方式就 ...

  6. Java调用SqlLoader将大文本导入数据库

    Java调用SqlLoader将大文本导入数据库 业务场景:将一千万条数据,大约500M的文本文档的数据导入到数据库 分析:通过Java的IO流解析txt文本文档,拼接动态sql实现insert入库, ...

  7. C++ 用 vector 生成三维数组,并计算行、列、高

    //Microsoft Visual Studio 2015 Enterprise //用vector生成三维数组,并计算行.列.高 #include <iostream> #includ ...

  8. 04 Python的继承、方法重写、super()类、父类私密属性的调用

    继承 A类继承B类,A即可获得B类的全部公共属性和方法(包括内置属性和方法).格式如:class A(B): class Animal: def sleep(self): print("zZ ...

  9. WUSTOJ 1307: 校门外的树(Java)

    题目链接:

  10. matplotlib实例笔记

    下面的图型是在一幅画布上建立的四个球员相关数据的极坐标图 关于这个图的代码如下: #_*_coding:utf-8_*_ import numpy as np import matplotlib.py ...