题目大意是有一个DIMA四种字母组成的矩阵,要在矩阵中找最长的DIMADIMADIMA……串,连接方式为四方向连接,问最长能找到多少DIMA。字母可以重复访问,如果DIMA串成环,即可以取出无限长的DIMA串,则输出特定字符串,若没有DIMA串,也输出另一特定字符串,否则输出最长多少DIMA串。

这是我大一暑假的时候做的,并且当时WA在第23组上,后来就没继续做这个题了,现在不想看大一的代码了。

重新想了一下,其实就是判图中是否有环,无环的话,DIMA的链最长多少,也就是找图中以D字母开头的最长链。

那么读入之后对D->I  I->M  M->A  A->D 进行建边,并判环以及求最长链即可。

我考虑判环和求最长链长度都可以通过DFS实现,所以就只写了一个DFS函数。

DFS当然是没有写错的,但是发现在第10组T了。想了一下,DFS总复杂度是O(n^2+m)的,m为边数,因为所有点和边都只会被DFS一次,我全部从D字母开始搜索。此时因为我判环有提前return的操作,会导致vis没有清空,因此我在每次DFS前有memset掉vis数组的操作。如果D特别多,则memset每次都是O(n^2)的复杂度,就会超时。我修改了一下,将DFS过程中的return前都将vis置为0,就不用memset了,于是就过了。

其实如果将判环和求最长链分开,或许就不会出现这样的问题,比如用拓扑序判环,肯定不会出现大量memset。判完环再求最长链,则已经知道图中没有环,DFS每个点必定只需要访问一次,就不需要memset了。

 #include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define MP make_pair
typedef long long ll;
const int mod = 1e9 + ;
const int INF = 0x3f3f3f3f;
const double eps = 1e-;
const int maxn = 1e6 + ; int n,m;
int xx[] = {,-,,};
int yy[] = {,,,-};
char s[][];
int id[][];
int dis[maxn];
int head[maxn],point[maxn<<],nxt[maxn<<],size;
int vis[maxn];
bool flag = false; void init(){
size = ;
memset(head,-,sizeof(head));
memset(dis,,sizeof(dis));
memset(vis,,sizeof(vis));
flag = false;
} void add(int a, int b){
point[size] = b;
nxt[size] = head[a];
head[a] = size++;
} void dfs(int s){
if(dis[s])return;
vis[s] = ;
dis[s] = ;
for(int i = head[s] ; ~ i ; i = nxt[i]){
int j = point[i];
if(vis[j]){flag = true;vis[s] = ;return;}
dfs(j);
if(flag){vis[s] = ;return;}
dis[s] = max(dis[s],dis[j]+);
}
vis[s] = ;
} int main(){
scanf("%d%d",&n,&m);
for(int i = ; i <= n ; ++ i)scanf("%s",s[i]+);
int cnt = ;
for(int i = ; i <= n ; ++ i){
for(int j = ; j <= m ; ++ j){
id[i][j] = ++ cnt;
}
}
init();
for(int i = ; i <= n ; ++ i){
for(int j = ; j <= m ; ++ j){
for(int k = ; k < ; ++ k){
int dx = i + xx[k];
int dy = j + yy[k];
if(dx < || dx > n || dy < || dy > m)continue;
if(s[i][j] == 'D' && s[dx][dy] == 'I')add(id[i][j],id[dx][dy]);
if(s[i][j] == 'I' && s[dx][dy] == 'M')add(id[i][j],id[dx][dy]);
if(s[i][j] == 'M' && s[dx][dy] == 'A')add(id[i][j],id[dx][dy]);
if(s[i][j] == 'A' && s[dx][dy] == 'D')add(id[i][j],id[dx][dy]);
}
}
}
int ans = ;
for(int i = ; i <= n ; ++ i){
for(int j = ; j <= m ; ++ j){
if(s[i][j] != 'D')continue;
dfs(id[i][j]);
if(flag == true){
printf("Poor Inna!\n");
return ;
}
if(dis[id[i][j]] > ans)ans = dis[id[i][j]];
}
}
ans /= ;
if(ans)printf("%d\n",ans);
else printf("Poor Dima!\n");
return ;
}

cf374C Inna and Dima dfs判环+求最长链的更多相关文章

  1. HDU 4612 Warm up tarjan缩环+求最长链

    Warm up Problem Description   N planets are connected by M bidirectional channels that allow instant ...

  2. cf1278D——树的性质+并查集+线段树/DFS判环

    昨天晚上本来想认真打一场的,,结果陪女朋友去了.. 回来之后看了看D,感觉有点思路,结果一直到现在才做出来 首先对所有线段按左端点排序,然后用并查集判所有边是否联通,即遍历每条边i,和前一条不覆盖它的 ...

  3. Atcoder Grand Contest 032C(欧拉回路,DFS判环)

    #include<bits/stdc++.h>using namespace std;int vis[100007];vector<int>v[100007];vector&l ...

  4. LG2272/BZOJ1093 「ZJOI2007」最大半连通子图 Tarjan缩点+DAG求最长链

    问题描述 LG2272 BZOJ1093 题解 观察半联通的定义,发现图中的一些结点,构成的链一定是一个半联通子图. 此时存在的环可能会干扰求解,于是\(\mathrm{Tarjan}\)缩点. 于是 ...

  5. Codeforces 374 C Inna and Dima (DFS)

    Inna and Dima 题意:从图上的任意一个D点按着DIMADIMA的顺序走,问一共可以经过多少个DIMA,如果经过0个DIMA就输出“Pool DIma!“,如果可以有无数多个DIMA就输出” ...

  6. 【题解】CF374C Inna and Dima

    题面传送门 解决思路 本题是找最长路的图上问题,所以先考虑如何建图. 首先把每一个字母转化为数字,然后对于每一个点枚举四个方向,如果有下一个字母,就向那个点建一条边,可以用 \(vector\) 存图 ...

  7. UVA818-Cutting Chains(二进制枚举+dfs判环)

    Problem UVA818-Cutting Chains Accept:393  Submit:2087 Time Limit: 3000 mSec  Problem Description Wha ...

  8. 洛谷2444(Trie图上dfs判环)

    要点 并没问具体方案,说明很可能不是构造. 思考不断读入这个文本串,然后中间不出现某些文法的串.啊,这就是个自动机. 将不合法串使用ac自动机构成一个Trie图,我们需要的字符串就是在这个自动机上无限 ...

  9. CodeForces-1217D (拓扑排序/dfs 判环)

    题意 https://vjudge.net/problem/CodeForces-1217D 请给一个有向图着色,使得没有一个环只有一个颜色,您需要最小化使用颜色的数量. 思路 因为是有向图,每个环两 ...

随机推荐

  1. [Linux] Configure iSCSI on Linux5 (both target and initiator)

    ********************************************************************************Target************** ...

  2. C++对象模型复习

    本文写于2017-02-24,从老账号迁移到本账号,原文地址:https://i.cnblogs.com/EditPosts.aspx?postid=6440685 一:对象模型 C++面向对象的实现 ...

  3. L1-062 幸运彩票

    彩票的号码有 6 位数字,若一张彩票的前 3 位上的数之和等于后 3 位上的数之和,则称这张彩票是幸运的.本题就请你判断给定的彩票是不是幸运的. 输入格式: 输入在第一行中给出一个正整数 N(≤ 10 ...

  4. 结对作业_core组

    github地址:https://github.com/ljw-wakeup/expression_project2 对于这种结对的工作,由于有过电子设计实践的基础,大概知道建一个工程需要做的事,有点 ...

  5. python基础学习之文件操作&函数

    1.文件处理相关 1.编码问题 ①python2与python3中的默认编码: py2默认使用ASCII码,py3默认使用utf-8 ②为什么会出现中文乱码,中文乱码的情况有哪些? #sys.stdo ...

  6. SharePoint Framework 在web部件中使用已存在的JavaScript库 - 捆绑打包和外部引用

    博客地址:http://blog.csdn.net/FoxDave 在构建SPFx客户端web部件时,你可以使用公网已有的JavaScript库来构建强大的解决方案.但是在使用的时候你需要考虑你引用的 ...

  7. VS添加WebService工具

    最近在做和WebService相关的项目,因为只是在学校里面用过,出来工作一直没有用到,所以不是很熟悉,于是自己配置了一个WebService工具给添加到了VS(VisualStudio)里面,其实就 ...

  8. `TypeError: torch.mm received an invalid combination of arguments - got (torch.FloatTensor, Variable),

    `TypeError: torch.mm received an invalid combination of arguments - got (torch.FloatTensor, Variable ...

  9. Beta冲刺 2

    前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/10104842.html 作业博客:https://edu.cnblogs.com/campus ...

  10. react-native-scrollable-tab-view 中嵌套了react-native-swiper产生的bug

    前段时间用RN的时候遇到过这个问题用scrollable-tab-view(scrollableView)这个组件然后嵌套轮播swiper会出现,在scrollableView  nitialPage ...