HDU - 5469 Antonidas —— dfs+剪枝

14 篇文章 0 订阅

题意:

树上的每个节点都有一个字母,问有没有一条路径上的字母是目标串

思路:

从每个符合第一个字母的地方搜索

搜索分为向父节点和子节点搜,向子节点搜时必须满足子节点子树的最大深度要大于剩余的目标串长度

所以要预处理出每个节点的父节点和节点子树的最大深度

搜索的时候记录每个点是否被访问过就A,但记录路径上这个点的上一个点就T,不知道为啥....

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define max_ 10005
#define mod 1000000007
int n,m;
vector< vector<int> >v;
char target[max_];
char w[max_];
int deph[max_];
int pre[max_];
bool vis[max_];
int casnum=1;
int pre_dfs(int x,int fa)
{
	pre[x]=fa;
	int maxx=0;
	for(int i=0;i<v[x].size();i++)
	{
		if(fa!=v[x][i])
		{
			maxx=max(pre_dfs(v[x][i],x),maxx);
		}
	}
	deph[x]=maxx;
	return maxx+1;
}
bool dfs(int x,int pos)
{
	if(pos==m+1)
	return true;
    vis[x]=true;
	if(x!=1&&vis[pre[x]]==false&&w[pre[x]]==target[pos])
	{
		if(dfs(pre[x],pos+1))
		return true;
	}
	if(deph[x]<m-pos+1)
	return false;
	for(int i=0;i<v[x].size();i++)
	{
		if((vis[v[x][i]]==false)&&(w[v[x][i]]==target[pos]))
		{
			if(dfs(v[x][i],pos+1))
			return true;
		}
	}
	return false;
}
int main(int argc, char const *argv[]) {
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		v.clear();
		v.resize(n+1);
		for(int i=1;i<n;i++)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			v[x].push_back(y);
			v[y].push_back(x);
		}
		scanf(" %s",w+1);
		scanf(" %s",target+1);
		pre_dfs(1,-1);
		m=strlen(target+1);
		if(m>=n)
		{
			printf("Case #%d: Impossible\n",casnum++ );
			continue;
		}
		int f=0;
		for(int i=1;i<=n;i++)
		{
			if(w[i]==target[1])
			{
                memset(vis,false,sizeof vis);
				if(dfs(i,2))
				{
					f=1;
					break;
				}
			}
		}
		if(f)
		printf("Case #%d: Find\n",casnum++ );
		else
		printf("Case #%d: Impossible\n",casnum++ );
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值