• cf374C Inna and Dima dfs判环+求最长链


    题目大意是有一个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了。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define PB push_back
     4 #define MP make_pair
     5 typedef long long ll;
     6 const int mod = 1e9 + 7;
     7 const int INF = 0x3f3f3f3f;
     8 const double eps = 1e-8;
     9 const int maxn = 1e6 + 5;
    10 
    11 int n,m;
    12 int xx[4] = {1,-1,0,0};
    13 int yy[4] = {0,0,1,-1};
    14 char s[1005][1005];
    15 int id[1005][1005];
    16 int dis[maxn];
    17 int head[maxn],point[maxn<<2],nxt[maxn<<2],size;
    18 int vis[maxn];
    19 bool flag = false;
    20 
    21 void init(){
    22     size = 0;
    23     memset(head,-1,sizeof(head));
    24     memset(dis,0,sizeof(dis));
    25     memset(vis,0,sizeof(vis));
    26     flag = false;
    27 }
    28 
    29 void add(int a, int b){
    30     point[size] = b;
    31     nxt[size] = head[a];
    32     head[a] = size++;
    33 }
    34 
    35 void dfs(int s){
    36     if(dis[s])return;
    37     vis[s] = 1;
    38     dis[s] = 1;
    39     for(int i = head[s] ; ~ i ; i = nxt[i]){
    40         int j = point[i];
    41         if(vis[j]){flag = true;vis[s] = 0;return;}
    42         dfs(j);
    43         if(flag){vis[s] = 0;return;}
    44         dis[s] = max(dis[s],dis[j]+1);
    45     }
    46     vis[s] = 0;
    47 }
    48 
    49 int main(){
    50     scanf("%d%d",&n,&m);
    51     for(int i = 1 ; i <= n ; ++ i)scanf("%s",s[i]+1);
    52     int cnt = 0;
    53     for(int i = 1 ; i <= n ; ++ i){
    54         for(int j = 1 ; j <= m ; ++ j){
    55             id[i][j] = ++ cnt;
    56         }
    57     }
    58     init();
    59     for(int i = 1 ; i <= n ; ++ i){
    60         for(int j = 1 ; j <= m ; ++ j){
    61             for(int k = 0 ; k < 4 ; ++ k){
    62                 int dx = i + xx[k];
    63                 int dy = j + yy[k];
    64                 if(dx < 1 || dx > n || dy < 1 || dy > m)continue;
    65                 if(s[i][j] == 'D' && s[dx][dy] == 'I')add(id[i][j],id[dx][dy]);
    66                 if(s[i][j] == 'I' && s[dx][dy] == 'M')add(id[i][j],id[dx][dy]);
    67                 if(s[i][j] == 'M' && s[dx][dy] == 'A')add(id[i][j],id[dx][dy]);
    68                 if(s[i][j] == 'A' && s[dx][dy] == 'D')add(id[i][j],id[dx][dy]);
    69             }
    70         }
    71     }
    72     int ans = 0;
    73     for(int i = 1 ; i <= n ; ++ i){
    74         for(int j = 1 ; j <= m ; ++ j){
    75             if(s[i][j] != 'D')continue;
    76             dfs(id[i][j]);
    77             if(flag == true){
    78                 printf("Poor Inna!
    ");
    79                 return 0;
    80             }
    81             if(dis[id[i][j]] > ans)ans = dis[id[i][j]];
    82         }
    83     }
    84     ans /= 4;
    85     if(ans)printf("%d
    ",ans);
    86     else printf("Poor Dima!
    ");
    87     return 0;
    88 }
    View Code

  • 相关阅读:
    Jsoup的学习
    String中对字符串进行操作的一些方法
    Httpclient的学习(一)
    初识爬虫见到的两个类 BufferedWriter和 BufferedReader
    ZooKeeper学习笔记(二)——内部原理
    FastDFS安装指南
    基于CentOS6.5的Dubbo及Zookeeper配置
    虚拟机克隆后遇到的网络相关的问题
    ElasticSerach 6.x的安装及配置
    YARN-HA高可用集群搭建
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/9639306.html
Copyright © 2020-2023  润新知