Antonidas
.
.
题意:给出一棵树,每个节点为一个字符,问能否从一个节点走到另一个节点(路径不重复),使得得出给定的字符串。
.
.
解法:dfs+剪枝。假设把1当作根节点,然后dfs一次记录每个节点往下最多能走多远。然后直接暴力dfs扫描能否有满足的路径,如果对于当前点要往下走就判断最远是否有可能完全匹配上,加上这个剪枝就可以过了。
.
.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <cstring>
#include <string>
const int maxn = 10010;
int tar[2*maxn], next[2*maxn], last[maxn], tot, dist[maxn];
int n, x, y, m;
char c[maxn], s[maxn];
bool flag;
void insert(int x, int y) {
tot++;
tar[tot] = y;
next[tot] = last[x];
last[x] = tot;
}
void Init(int x, int pre) {
dist[x] = 1;
int k = last[x];
while (k != 0) {
if (tar[k] == pre) {
k = next[k];
continue;
}
Init(tar[k], x);
dist[x] = dist[x]>dist[tar[k]]+1 ? dist[x]:dist[tar[k]]+1;
k = next[k];
}
}
void dfs(int x, int pre, int t) {
if (t > m) {
flag = true;
return;
}
int k = last[x];
while (k != 0) {
if (tar[k] == pre || c[tar[k]] != s[t]) {
k = next[k];
continue;
}
if (dist[x] > dist[tar[k]] && dist[tar[k]]-1 < m-t) {
k = next[k];
continue;
}
dfs(tar[k], x, t+1);
k = next[k];
if (flag) return;
}
}
int main() {
int tt, cases = 0;;
scanf("%d", &tt);
while (tt--) {
scanf("%d", &n);
memset(last, 0, sizeof(last));
memset(dist, 0, sizeof(dist));
tot = 0;
m = 0;
flag = false;
for (int i = 1; i < n; i++) {
scanf("%d %d", &x, &y);
insert(x, y);
insert(y, x);
}
Init(1, 0);
for (int i = 0; i <= n; i++) scanf("%c", &c[i]);
char ch = getchar();
while (scanf("%c", &ch) != EOF) {
if (ch == '\n') break;
s[++m] = ch;
}
for (int i = 1; i <= n; i++) if (c[i] == s[1]) {
dfs(i, 0, 2);
if (flag) break;
}
printf("Case #%d: ", ++cases);
if (flag) printf("Find\n");
else printf("Impossible\n");
}
}