zoukankan      html  css  js  c++  java
  • Hiho1041 国庆出游 搜索题解

    题目3 : 国庆出游

    时间限制:1000ms
    单点时限:1000ms
    内存限制:256MB

    描写叙述

    小Hi和小Ho准备国庆期间去A国旅游。A国的城际交通比較有特色:它共同拥有n座城市(编号1-n);城市之间恰好有n-1条公路相连,形成一个树形公路网。小Hi计划从A国首都(1号城市)出发,自驾遍历全部城市,而且经过每一条公路恰好两次——来回各一次——这样公路两旁的景色都不会错过。


    令小Hi苦恼的是他的小伙伴小Ho希望能以某种特定的顺序游历当中m个城市。

    比如按3-2-5的顺序游历这3座城市。(详细来讲是要求:第一次到达3号城市比第一次到达2号城市早。而且第一次到达2号城市比第一次到达5号城市早)。


    小Hi想知道是否有一种自驾顺序满足小Ho的要求。

    输入

    输入第一行是一个整数T(1<=T<=20),代表測试数据的数量。

    每组数据第一行是一个整数n(1 <= n <= 100),代表城市数目。

    之后n-1行每行两个整数a和b (1 <= a, b <= n)。表示ab之间有公路相连。

    之后一行包括一个整数m (1 <= m <= n)

    最后一行包括m个整数,表示小Ho希望的游历顺序。

    输出

    YES或者NO,表示是否有一种自驾顺序满足小Ho的要求。

    例子输入
    2
    7
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    3
    3 7 2
    7
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    3
    3 2 7
    
    例子输出
    YES
    NO
    好吧,第一次写hiho的题目,一个新起的oj站点。

    这次是微软的预測赛。站点有点偷懒啊,用了曾经的题目拼凑起来的一个比赛。只是眼下站点的题量本来就不多。


    本题是第三题,本来应该不难。就是一个深度搜索的题目。

    哎。我悲剧了,还是没能按时完毕,最后还是參考了一下网上程序,自己写了个。

    看来自己火候还是不够。难怪进不了Google面试,好好继续努力吧。


    眼下在找工作。想找技术管理这块工作,真忧虑自己做不成自己想做的东西。

    一个不知名的学校真有这么大的不便,令人意想不到啊;经历了,又会认为情理之中,一切都是人性。心态放开点吧。

    尽管亚历山大。还是须要继续坚持学习的。

    拒了网易运营笔试,拒了聚美什么的笔试,你们要找名校就不要找我玩了。真不想陪你们玩了;面试官的算法题直接被我完美秒杀,连一个小bug你都找不到,都能够拒我的, I服了you!

    既然我学校不知名,那我就去小点不那么知名的公司吧,以我的热诚,我相信我能够!


    这是一个挺有技巧的深度搜索,须要优化,并且是利用位运算优化。很巧妙。

    基本的思想是一个消除查找的思想。就是给出两个集合。求交集的算法的高级应用。

    求交集的思想非常easy,就是排序,然后一遍搜索就能够找出了。


    这里是在树上求可行的一个序列集合:

    加速:这里的getChild函数就是预处理一个节点以下有什么子节点,处理完之后就能够在O(1)的时间内能够推断有没有一个特定的子节点。

    然后eliminateAll就是上面说的消除查找思想,代码不长。只是当中有非常多细节点,须要好好认真考究,当中的关键点代码中标注出来了。


    #include <stdio.h>
    #include <vector>
    #include <string.h>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <limits.h>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <bitset>
    using namespace std;
    
    const int MAX_N = 101;
    vector<int> graAdj[MAX_N];//邻接表
    int arr[MAX_N];
    int graMat[MAX_N][MAX_N];//矩阵
    
    bitset<MAX_N> hasChild[MAX_N];
    void getChild(int u = 1, int par = -1)
    {
    	hasChild[u][u] = 1;	//自己是自己的孩子?把自己也并进孩子集合中。
    	for (int i = 0; i < (int)graAdj[u].size(); i++)
    	{
    		int v = graAdj[u][i];
    		if (v == par) continue;//防止回路,不回走父亲节点
    		getChild(v, u);
    		hasChild[u] |= hasChild[v];//巧妙利用bitset加速推断一个节点有多少孩子
    	}
    }
    
    //利用全局变量graMat和graAdj
    bool eliminatAll(int a[], int &id, int m, int u = 1, int par = -1)
    {
    	if (id < m && a[id] == u) id++;
    	if (id == m) return true;
    
    	while (id < m)//关键点,能够循环查找子节点
    	{
    		int nexta = a[id];
    		int curIndex = id;
    		for (int i = 0; i < (int)graAdj[u].size(); i++)
    		{
    			int v = graAdj[u][i];
    			if (v == par) continue;//排除父节点。防止回路
    
    			if (hasChild[v][nexta] && graMat[u][v])
    			{
    				graMat[u][v] = 0;//关键点:拆桥。不用反复查找路径
    				if (eliminatAll(a, id, m, v, u)) return true;
    			}
    		}
    		//关键点:防止无限循环。没有答案的时候退出
    		if (id == curIndex) break;//没有找到一个相应的点a[id]。返回上一层
    	}
    	return false;
    }
    
    int main()
    {
    	int T, n, a, b, m;
    	scanf("%d", &T);
    	while (T--)
    	{
    		scanf("%d", &n);
    		for (int i = 1; i <= n; i++)
    		{
    			graAdj[i].clear();
    			hasChild[i].reset();
    		}
    		memset(graMat, 0, sizeof(graMat));
    
    		for (int i = 1; i < n; i++)
    		{
    			scanf("%d %d", &a, &b);
    			graAdj[a].push_back(b);
    			graAdj[b].push_back(a);
    			graMat[a][b] = graMat[b][a] = 1;
    		}
    
    		scanf("%d", &m);
    		for (int i = 0; i < m; i++)
    		{
    			scanf("%d", arr+i);
    		}
    
    		getChild();
    
    		int id = 0;
    		if (eliminatAll(arr, id, m)) puts("YES");
    		else puts("NO");
    	}
    	return 0;
    }



  • 相关阅读:
    django 常用命令
    nginx+gunicorn
    终于决定写个技术博客
    test
    自定义控件
    .net mvc 发布部署到机器上
    C# StringExt 字符串扩展
    MYSQL连接数据库
    List IEnumerable
    CentOS安装pip
  • 原文地址:https://www.cnblogs.com/jhcelue/p/7146531.html
Copyright © 2011-2022 走看看