Appoint description:
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.
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”.
If the path exists, please output “Find”. Otherwise, please output “Impossible”.
Sample Input
2 7 1 2 2 3 2 4 1 5 5 6 6 7 abcdefg dbaefg 5 1 2 2 3 2 4 4 5 abcxy yxbac
Sample Output
Case #1: FindCase #2: Impossible
题意:给一棵树,每个节点上有一个字母,又有一个字符串S,问在树上是否有这样一个起点和终点使得路径上的字母形
成的串和串S相同;
有10000个节点,暴力搜索会超时,亲自试过,需要进行优化,每次从在树上的字母S[0]出发,向下或者向上搜索,判断
条件是S串要匹配的字母与树上的下一个节点表示字母相同,且由下一个节点出发向下可以到达的最远距离要大于剩余匹配长度,在寻找树上下一个节点时,可以向下也可以向上,只要满足条件即可,这其实救赎树上的分治思想,在每个节点分为向
上和向下,当匹配长度=S的length时返回true
事先处理dist【】数组,保存每个节点可以向下到达的最远距离
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <stdlib.h> #include <queue> using namespace std; const int maxn=1e4+10; struct Edge { int to,next; } edge[maxn*2]; int tot,head[maxn]; void init() { tot=0; memset(head,-1,sizeof(head)); } void add(int u,int v) { edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } int dist[maxn],par[maxn]; void dfs1(int u,int pre) { par[u]=pre; int mx=0; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; if(v!=pre) { dfs1(v,u); mx=max(dist[v],mx); } } dist[u]=mx+1; } int len,vis[maxn]; char str[maxn],s[maxn]; bool dfs2(int u,int le) { int v,fa=par[u]; vis[u]=1; if(le==len) return true; for(int i=head[u];i!=-1;i=edge[i].next) { v=edge[i].to; if(v!=fa&&!vis[v]&&str[v]==s[le]&&(len-le)<=dist[v]) if(dfs2(v,le+1)) return true; } if(!vis[fa]&&str[fa]==s[le]) if(dfs2(fa,le+1)) return true; return false; } int main() { int n; int u,v; int T; cin>>T; for(int cas=1; cas<=T; cas++) { scanf("%d",&n); init(); for(int i=1; i<n; i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } scanf("%s",str+1); scanf("%s",s); len=strlen(s); dfs1(1,0); printf("Case #%d: ",cas); for(int i=1; i<=n; i++) { if(str[i]==s[0]) { memset(vis,0,sizeof(vis)); if(dfs2(i,1)) { puts("Find"); goto endW; } } } puts("Impossible"); endW: ; } return 0; }