HDU 5469 Antonidas dfs减枝

来源:互联网 发布:用户标签数据库设计 编辑:程序博客网 时间:2024/05/16 18:49

题目描述:

Problem Description
Given a tree with N vertices and N−1 edges. Each vertex has a single letter Ci. Given a string S, you are to choose two vertices A and B, and make sure the letters catenated on the shortest path from A to B is exactly S. Now, would you mind telling me whether the path exists?

Input
The first line is an integer T, the number of test cases.
For each case, the first line is an integer N. Following N−1 lines contains two integers a and b, meaning there is an edge connect vertex a and vertex b.
Next line contains a string C, the length of C is exactly N. String C represents the letter on each vertex.
Next line contains a string S.
1≤T≤200, 1≤N≤104, 1≤a,b≤N, a≠b, |C|=N, 1≤|S|≤104. String C and S both only contain lower case letters.

Output
First, please output “Case #k: “, k is the number of test case. See sample output for more detail.
If the path exists, please output “Find”. Otherwise, please output “Impossible”.

Sample Input

271 22 32 41 55 66 7abcdefgdbaefg51 22 32 44 5abcxyyxbac

Sample Output

Case #1: FindCase #2: Impossible

Source
2015 ACM/ICPC Asia Regional Shanghai Online

题目分析:

给你一颗n个节点,n-1条边的树,其中树的标号由1到n,用一个字符串C来对应这颗树(每一个字符对应相应的节点),再给定一个字符串S,求这个字符串序列所代表的树节点的遍历序列是否能在这颗树上实现?

开始我觉得是一个简单的dfs搜索问题,从每一个点对应的节点搜索,记录搜索是否到终点,即可。然后提交不对,看了其它博客上写的是树上分治,其实这个题dfs是能写的,但是需要减枝将每个节点的深度和其父节点标记,然后再一次搜索的过程中需要减去那些不可能的情况(S字符串长度减去当前搜索深度已经超过该节点的深度),即可。

代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>using namespace std;const int MAXN=1e5+10;struct node{    int u,pre,dep;    node (int u=0, int pre=0, int dep=0): u(u), pre(pre), dep(dep) {}};struct Edge{    int to,next;} G[MAXN];int head[MAXN],tot;int fa[MAXN],dep[MAXN];char str1[MAXN],str2[MAXN];int n;int len,len2;int T;void init(){    memset(head,-1,sizeof(head));    tot=0;}void addedge(int u,int v){    G[tot].to=v;    G[tot].next=head[u];    head[u]=tot++;}int dfs(int u,int pre){    fa[u]=pre;    int d=0;    for(int i=head[u]; i!=-1; i=G[i].next)    {        int v=G[i].to;        if (v==pre) continue;;        d=max(dfs(v,u),d);    }    return dep[u]=d+1;}bool judge (){    queue<node> Q;    for (int i=1; i<=n; i++)        if (str1[i]==str2[1])            Q.push(node(i,-1,1));    while(!Q.empty())    {        node cur=Q.front();        Q.pop();        int u=cur.u, pre=cur.pre, depth=cur.dep;        if (pre==fa[u] && len2-depth>=dep[u]) continue;//减枝操作        for (int i=head[u]; i!=-1; i=G[i].next)        {            int v=G[i].to;            if (v==pre || str1[v]!=str2[depth+1]) continue;            if (depth+1==len2) return true;            Q.push(node(v,u,depth+1));        }    }    return false;}int main(){    int cas=0;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        init();        for(int i=1; i<n; i++)        {            int u,v;            scanf("%d%d",&u,&v);            addedge(u,v);            addedge(v,u);        }        dfs(1,-1);        scanf("%s",str1+1);        scanf("%s",str2+1);        len2=strlen(str2+1);        bool f=judge();        printf("Case #%d: ",++cas);        if (f) printf("Find\n");        else printf("Impossible\n");    }    return 0;}
0 0
原创粉丝点击