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

     

  • 相关阅读:
    UI进阶--手势识别
    UI进阶--响应者链条
    UI进阶--触摸事件的产生和传递
    UI进阶--触摸事件
    UI进阶--Quartz2D和触摸事件的简单使用:手势解锁
    UI进阶--Quartz2D和触摸事件的简单使用:简易涂鸦板
    UI进阶--Quartz2D绘制图形的基本使用
    Mac 自定义"终端"快捷键
    GCD内部实现--摘自《iOS与OS X多线程和内存管理》
    Add Binary -- leetcode
  • 原文地址:https://www.cnblogs.com/mypride/p/4847461.html
Copyright © 2011-2022 走看看