• 【hiho1041】国庆出游 dfs+bitset


    题目大意:给定一棵 N 个节点的有根树,1 号节点为根节点,现遍历整棵树,要求每条边仅被经过两次,问是否存在一种特定的遍历方式使得 dfs 序中节点的相对前后关系符合给定的顺序。

    题解:
    首先,由于要求每条边仅能经过两次,可知若正在遍历当前节点 u,则以 u 为根节点的子树中的所有节点都必须遍历,因此遍历子树的顺序十分重要。我们可以提前预处理出树上每个节点能够到达以该节点为根的子树中的节点编号,并维护一个当前指针,指向给定顺序的序列,若某棵子树中有当前指针指向的点,则遍历该子树。

    代码如下

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    const int maxn=110;
    
    vector<int> G[maxn];
    bitset<maxn> f[maxn];
    int n,m,go[maxn],now;
    bool vis[maxn];
    
    void dfs1(int u,int fa){
    	f[u][u]=1;
    	for(auto v:G[u]){
    		if(v==fa)continue;
    		dfs1(v,u);
    		f[u]|=f[v];
    	}
    }
    bool dfs2(int u){
    	if(u==go[now])++now;
    	if(now==m+1)return 1;
    	vis[u]=1;
    	while(1){
    		bool has=0;
    		int need=go[now];
    		for(auto v:G[u]){
    			if(vis[v])continue;
    			if(f[v][need]){
    				has=1;
    				if(dfs2(v))return 1;
    			}
    		}
    		if(!has)return 0;
    	}
    	return 0;
    }
    void read_and_parse(){
    	scanf("%d",&n);
    	for(int i=1;i<n;i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		G[x].pb(y),G[y].pb(x);
    	}
    	scanf("%d",&m);
    	for(int i=1;i<=m;i++)scanf("%d",&go[i]);
    }
    void solve(){
    	dfs1(1,0);
    	now=1;
    	puts(dfs2(1)?"YES":"NO");
    }
    void init(){
    	for(int i=1;i<=n;i++)G[i].clear(),f[i].reset();
    	memset(vis,0,sizeof(vis));
    }
    int main(){
    	int T;scanf("%d",&T);
    	while(T--){
    		init();
    		read_and_parse();
    		solve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    jsp 页面获取当前路径
    html5 页面音频
    微信关于网页授权access_token和普通access_token的区别
    Texlive source
    vscode 快捷键
    vscode setting
    vscode extension 插件管理
    what
    linux manual
    java tool type
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10944324.html
Copyright © 2020-2023  润新知