UVALive 3486

题意: 给一棵树,每次每次询问一个点是否是另一个点的祖先?
输入父节点和它的儿子,数据量大,所以用栈结构防爆;

对于查询是否是祖先,我们可以对于每一个节点打上两个dfs标记,如果一个点是另一个点的祖先,那么它的两个标记一定在祖先的范围之内。【tarjan的时间戳的概念】

注意每个样例输出之间要输空行

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<algorithm>
#define maxn 20022000
using namespace std;
typedef long long ll;
int n;
int child[maxn];
stack<int>st;
int clockk=0;
int vis[maxn];

struct a{
	int l,r;
}state[maxn];
struct b{
	int in,out;
}dfn[maxn];

void init(){
	clockk=0;
	while(!st.empty()) st.pop();
//	for(int i=0;i<maxn;i++)
}

void dfs(){
	for(int i=0;i<maxn;i++) vis[i]=0;
	st.push(0);
	while(!st.empty()){
		int x=st.top();
		if(!vis[x]){
			vis[x]=1;
			dfn[x].in=clockk++;
			if(x<n){
				int lchild=state[x].l,rchild=state[x].r;
				for(int i=lchild;i<=rchild;i++)	st.push(i);
			}
		}
		else{
			st.pop();
			dfn[x].out=clockk++;	
		}

	}
}


int main(){
	int T,x,m;
	scanf("%d",&T);
	int cas=0;
	while(T--){
		init();
		scanf("%d",&n);
		int y=1;
		for(int i=0;i<n;i++){
			scanf("%d",&x);
			state[i].l=y;
			state[i].r=y+x-1;
			y+=x;
		}
		dfs();
/*		for(int i=0;i<10;i++){
			printf("i=%d dfn[i].in=%d out=%d\n",i,dfn[i].in,dfn[i].out);
		}
*/		int u,v;
		scanf("%d",&m);
		if(cas++) printf("\n");
		printf("Case %d:\n",cas);
		for(int i=1;i<=m;i++){
			scanf("%d%d",&u,&v);
			bool f=false;
		//	printf("u=%d v=%d\n",u,v);
			if(dfn[u].in<dfn[v].in&&dfn[u].out>dfn[v].out)	printf("Yes\n");
			else printf("No\n");
		}
		
	}

	return 0;
} 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fedsnly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值