zoukankan      html  css  js  c++  java
  • hdu 5469 Antonidas (dfs+剪枝)2015 ACM/ICPC Asia Regional Shanghai Online

    题意:

    给出一棵树,再给出每个节点上的值(一个char字符)这些值以一个字符串s1表示,然后给出一个s2字符串,问在这棵树上是否存在两个点,从一个点走到另一个点所经过的路径上的char字符组成的字符串正好等于s1。问是否存在这么两个点。如果存在,则输出“Find”,否则,输出“Important”。

     

    题解:

    使用dfs就可以解决,但是需要进行剪枝,否则就会tle

    剪枝的方法是这样的——假设节点1是根节点,然后我们先使用一次dfs记录每个节点到叶节点的最长的路径dis[x]

    然后开始搜索,每次搜到当前点xdis[x],如果dis[x]>剩下的字符串s1的值,那么可以走这条路,否则就不走这条路,看这个点的父节点是否满足。

    上面那句话可能有些难以理解,具体来讲就是这个意思——如果从当前节点ch向它的叶节点走,需要满足的条件是从点ch到离她最远的叶节点的长度要大于剩余的未匹配的s2串的长度。如果向ch的父节点走,那么就不需要判断了(其实也可以判断,只是要么很麻烦,要么没必要,如果有即简洁又有效的方法,洗耳恭听)。

     

    具体见代码:

     

     

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 const int N = 10010;
      8 
      9 struct Edge
     10 {
     11     int to, next;
     12 }edge[N<<1];        //前向星标,记录邻接表
     13 
     14 int head[N], fm[N];     //节点i的edge[]下标 / 节点i的父节点
     15 int dis[N];             //节点i到最远叶节点的长度
     16 bool vis[N];
     17 int n, t, k;
     18 int len;
     19 char s1[N], s2[N];      //源串与匹配串
     20 
     21 void add(int u, int v)
     22 {
     23     edge[k].to = v;
     24     edge[k].next = head[u];
     25     head[u] = k++;
     26 }
     27 
     28 void tdfs(int x)
     29 {
     30     int mdis = -1;
     31     for(int i = head[x]; i != -1; i = edge[i].next)
     32     {
     33         int v = edge[i].to;
     34         if(!vis[v])
     35         {
     36             vis[v] = 1;
     37             tdfs(v);
     38             fm[v] = x;
     39             mdis = mdis > dis[v] ? mdis : dis[v];
     40         }
     41     }
     42     dis[x] = mdis == -1 ? 1 : mdis+1;       //记录每个节点到最远的叶节点的长度
     43 }
     44 
     45 bool dfs(int x, int disx, int mlen)         //核心dfs
     46 {
     47     if(disx-1 > len) return 1;              //如果已匹配的长度已超过匹配串长度,即,存在这么一个串,及时返回1
     48     if(dis[x] > mlen)                       //如果向叶节点走路径长度大于剩下未匹配的串的长度,则向这个方向走
     49     {
     50         for(int i = head[x]; i != -1; i = edge[i].next)
     51         {
     52             int v = edge[i].to;
     53             if(!vis[v] && s1[v] == s2[disx])
     54             {
     55                 vis[v] = 1;
     56                 if(dfs(v, disx+1, mlen-1)) return 1;
     57             }
     58         }
     59     }
     60     if(!vis[fm[x]] && s1[fm[x]] == s2[disx])    //向父节点搜索
     61     {
     62         vis[fm[x]] = 1;
     63         return dfs(fm[x], disx+1, mlen-1);
     64     }
     65     return 0;                                   //都不存在,则返回0
     66 }
     67 
     68 void init()
     69 {
     70     scanf("%d", &n);
     71     k = 0;
     72     memset(head, -1, sizeof(head));
     73     for(int i = 0; i < n; i++)
     74     {
     75         int a, b;
     76         scanf("%d%d", &a, &b);
     77         add(a, b);
     78         add(b, a);
     79     }
     80     memset(dis, 0, sizeof(dis));
     81     memset(vis, 0, sizeof(vis));
     82     tdfs(1);
     83     scanf("%s%s", s1+1, s2+1);
     84     len = strlen(s2+1)-1;
     85 }
     86 
     87 int main()
     88 {
     89     //freopen("test.in", "r", stdin);
     90     scanf("%d", &t);
     91     for(int tm = 1; tm <= t; tm++)
     92     {
     93         init();
     94         bool flag = 0;
     95         for(int i = 1; i <= n; i++)
     96         {
     97             if(s1[i] == s2[1])
     98             {
     99                 memset(vis, 0, sizeof(vis));
    100                 if(dfs(i, 2, len))
    101                 {
    102                     flag = 1;
    103                     break;
    104                 }
    105             }
    106         }
    107         printf("Case #%d: ", tm);
    108         if(flag) printf("Find
    ");
    109         else printf("Impossible
    ");
    110     }
    111     return 0;
    112 }
    View Code

     

  • 相关阅读:
    HDU 2899 Strange fuction
    HDU 2899 Strange fuction
    HDU 2199 Can you solve this equation?
    HDU 2199 Can you solve this equation?
    Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)
    Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)
    Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)
    Java实现 LeetCode 699 掉落的方块(线段树?)
    Java实现 LeetCode 699 掉落的方块(线段树?)
    Java实现 LeetCode 699 掉落的方块(线段树?)
  • 原文地址:https://www.cnblogs.com/mypride/p/4847461.html
Copyright © 2011-2022 走看看