标签:
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\leq T\leq 200, 1\leq N\leq 10^4, 1\leq a,b\leq N, a\not = b, |C|=N, 1\leq |S|\leq 10^4$. 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”.
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
Case #1: Find Case #2: Impossible
1 #include <bits/stdc++.h> 2 using namespace std; 3 using ULL = unsigned long long; 4 const int maxn = 10010; 5 const ULL Base = 31; 6 struct arc{ 7 int to,next; 8 arc(int x = 0,int y = -1){ 9 to = x; 10 next = y; 11 } 12 }e[maxn<<1]; 13 bool vis[maxn]; 14 int head[maxn],sz[maxn],maxson[maxn],pre[maxn],suf[maxn],tot,len,cnt; 15 ULL Pre[maxn],Suf[maxn],B[maxn] = {1}; 16 char sa[maxn],sb[maxn]; 17 void add(int u,int v){ 18 e[tot] = arc(v,head[u]); 19 head[u] = tot++; 20 } 21 void dfs(int u,int fa){ 22 sz[u] = 1; 23 maxson[u] = 0; 24 for(int i = head[u]; ~i; i = e[i].next){ 25 if(e[i].to == fa || vis[e[i].to]) continue; 26 dfs(e[i].to,u); 27 sz[u] += sz[e[i].to]; 28 maxson[u] = max(maxson[u],sz[e[i].to]); 29 } 30 } 31 int FindRoot(int sum,int u,int fa){ 32 int ret = u; 33 maxson[u] = max(maxson[u],sum - sz[u]); 34 for(int i = head[u]; ~i; i = e[i].next){ 35 if(e[i].to == fa || vis[e[i].to]) continue; 36 int x = FindRoot(sum,e[i].to,u); 37 if(maxson[x] < maxson[ret]) ret = x; 38 } 39 return ret; 40 } 41 bool cao(int u,ULL w,int fa,int depth,bool op) { 42 if(depth > len) return false; 43 w = w*Base + (ULL)sa[u]; 44 if(op) { 45 if(w == Pre[depth] && suf[depth] == cnt) return true; 46 if(w == Suf[len - depth + 1] && pre[len - depth + 1] == cnt) return true; 47 } else { 48 if(w == Pre[depth]) pre[depth] = cnt; 49 if(w == Suf[len - depth + 1]) suf[len - depth + 1] = cnt; 50 } 51 for(int i = head[u]; ~i; i = e[i].next) { 52 if(vis[e[i].to] || e[i].to == fa) continue; 53 if(cao(e[i].to,w,u,depth + 1,op)) return true; 54 } 55 return false; 56 } 57 bool solve(int u){ 58 dfs(u,0); 59 if(sz[u] < len) return false; 60 int root = FindRoot(sz[u],u,0); 61 vis[root] = true; 62 ++cnt; 63 ULL w = sa[root]; 64 if(w == Pre[len]) return true; 65 if(w == Pre[1]) pre[1] = cnt; 66 if(w == Suf[len]) suf[len] = cnt; 67 for(int i = head[root]; ~i; i = e[i].next){ 68 if(vis[e[i].to]) continue; 69 if(cao(e[i].to,w,root,2,true)) return true; 70 cao(e[i].to,w,root,2,false); 71 } 72 for(int i = head[root]; ~i; i = e[i].next){ 73 if(vis[e[i].to]) continue; 74 if(solve(e[i].to)) return true; 75 } 76 return false; 77 } 78 int main(){ 79 int kase,n,u,v,cs = 1; 80 for(int i = 1; i < maxn; ++i) B[i] = B[i-1]*Base; 81 scanf("%d",&kase); 82 while(kase--){ 83 scanf("%d",&n); 84 memset(head,-1,sizeof head); 85 memset(vis,false,sizeof vis); 86 memset(pre,0,sizeof pre); 87 memset(suf,0,sizeof suf); 88 tot = 0; 89 for(int i = 1; i < n; ++i){ 90 scanf("%d%d",&u,&v); 91 add(u,v); 92 add(v,u); 93 } 94 scanf("%s%s",sa + 1,sb + 1); 95 len = strlen(sb + 1); 96 for(int i = 1; i <= len; ++i) Pre[i] = Pre[i-1] + B[i-1]*sb[i]; 97 Suf[len + 1] = 0; 98 for(int i = len; i > 0; --i) Suf[i] = Suf[i+1] + B[len - i]*sb[i]; 99 printf("Case #%d: %s\n",cs++,solve(1)?"Find":"Impossible"); 100 } 101 return 0; 102 }
标签:
原文地址:http://www.cnblogs.com/crackpotisback/p/4908870.html