zoukankan      html  css  js  c++  java
  • hihocoder 1041 国庆出游 dfs

    传送门:hihocoder 1041

            给定一棵树,从节点1出发。

    如今要求一种遍立方法,使得全部边都来回各走一遍,问在这样的条件下能否按指定顺序訪问部分点


            比較巧妙的dfs深搜。

    默认1为根节点,因此从1节点出发,预处理出每一个节点的子树中能达到的节点。

    然后进行深搜,深搜策略例如以下:

            对根节点開始,若找到某一个子节点能到达目标节点,且走向该节点的路径没有訪问过,则走向子节点继续深搜直至按指定顺序訪问全然部节点,或者某一节点已不可达

    /******************************************************
     * File Name:   1041.cpp
     * Author:      kojimai
     * Create Time: 2014年10月31日 星期五 12时43分10秒
    ******************************************************/
    
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<bitset>
    using namespace std;
    #define FFF 105
    int a[FFF],first[FFF],e,cnt = 0,num,next[FFF*2],v[FFF*2];
    bitset<FFF> shao[FFF];//用bitset来存每一个节点的子节点中能到达点的情况
    bool vis[FFF*2],ans;
    void addedge(int x,int y)
    {
    	v[e] = y;next[e] = first[x];first[x] = e++;
    	v[e] = x;next[e] = first[y];first[y] = e++;
    }
    
    void solve_can(int now,int fa)//处理出now节点的子树中能到达的点
    {
    	shao[now][now] = 1;//首先自身能到达自身位置
    	for(int k = first[now]; ~k;k = next[k])
    	{
    		int val = v[k];
    		if(val == fa)
    			continue;
    		solve_can(val,now);//找出子节点的子树中能到达的点
    		shao[now] |= shao[val];//子节点能到达的点,当前点也能到,用bitset处理能够直接用或运算比較快捷
    	}
    	return;
    }
    
    void solve(int now,int fa)
    {
    	if(now == a[cnt])//訪问到指定顺序的点,则准备訪问下一个点
    	{
    		cnt++;
    	}
    	if(cnt == num)
    	{
    		ans = true;//全部点都訪问完了,则说明最后可行
    		return;
    	}
    	while(cnt < num)
    	{
    		int tmp = cnt;
    		for(int k = first[now]; ~k;k = next[k])
    		{
    			int val = v[k];
    			if(val == fa)
    				continue;
    			if(shao[val][a[cnt]] && !vis[k])//目标点可达且该条路没有訪问过,则向下深搜
    			{
    				vis[k] = true;//标记路径已经訪问过
    				solve(val,now);
    				break;
    			}
    		}
    		if(tmp == cnt)//假如当前节点无法到达指定顺序的点或者路径已訪问过不能走则返回父节点继续深搜
    			break;
    	}
    	return;
    }
    
    int main()
    {
    	int keng;
    	scanf("%d",&keng);
    	while(keng--)
    	{
    		ans = false;
    		int x,y;
    		memset(first,-1,sizeof(first)); e = 0;
    		int n;
    		scanf("%d",&n);
    		for(int i = 1;i < n;i++)
    		{
    			scanf("%d%d",&x,&y);
    			addedge(x,y);
    		}
    
    		scanf("%d",&num);
    		for(int i = 0;i < num;i++)
    			scanf("%d",&a[i]);
    
    		for(int i = 1;i <= n;i++)
    			shao[i].reset();
    
    		solve_can(1,-1);//预处理每一个点的子树能到达哪些点
    
    		memset(vis,false,sizeof(vis));
    		cnt = 0;//记录按顺序已经訪问到第几个点
    		solve(1,-1);
    		if(ans)
    			printf("YES
    ");
    		else
    			printf("NO
    ");
    	}
    	return 0;
    }
    


  • 相关阅读:
    delphi验证码识别之如何识别高级验证码
    delphi验证码识别学习之图像的灰度化、二值化及反色
    js 数字,金额 用逗号 隔开。数字格式化
    fedora linux 下安装pwntcha[验证码开源]
    C#的多线程机制探索4
    【一天的作息时间】.....程序员们,好好看看
    我的图像之路之CAPTCHA 和 break CAPTCHA
    C#格式化字符串
    struts2拦截器
    java动态代理(JDK和cglib)
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7047140.html
Copyright © 2011-2022 走看看