zoj 2838 Utopia

本文介绍了一个关于在特殊构型的Utopia村庄网络中查询特定路径的问题,并提供了一种利用LCA模版进行有效查询的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Utopia

Time Limit: 5 Seconds      Memory Limit: 32768 KB

Few people know a secret nation in the world named Utopia. But I have been there before, where there are many beautiful villages. Seeing from the space, you will find that all the villages are connected together via some roads such that there is one and only one path between every two villages.

One day, when I was taking photos of this country, I met a handsome young man named Pierre who looked very worried. So I came up and wondered if I could do something for him. He told me that he had fallen in love with Mary, the most beautiful girl in his village A.

Every morning, Mary went to work in a bakery shop in the village B and she came home at 6 p.m in the evening. After a long time, Pierre couldn't wait telling Mary that he loved her, so he decided to wait for Mary and tell her his love in the village C.

Unfortunately, Pierre was not sure if C was on the path between B and his own village. He felt very upset.

Pierre's love moved me, but you know, I was a stranger there myself, and I knew little about Utopia. Therefore, I stayed with Pierre and waited for the help of some Wiseman.

Can you help him?

Input

There are multiple test cases for this problem.

Each test case starts with a line containing an integer N (1 <= N <= 50000), representing that there are totally N villages (indexed from 0 to N-1), followed by N - 1 lines which provide the road information in Utopia. Each line with the form 'V1 V2' (without quotation, 0 <= V1, V2 <= N-1) means that there is a bidirectional road between village V1 and V2. Then it's an integer M (1 <= M <= 500000), followed by M queries, each query is in the form of 'A B C' (without quotation, 0 <= A, B, C <= N-1) in a single line.

Output

For each test case, output "Case #:" first. "#" is the number of the case, which starts from 1. Then for each query 'A B C', if village C is on the path between village A and B, output 'Yes' (without quotation) in a single line, otherwise output 'No' (without quotation).

Separate two consecutive test cases with a blank line, but Do NOT output an extra blank line after the last one.

Sample Input

3
0 1
1 2
3
0 2 1
1 2 0
1 2 1

Sample Output

Case 1:
Yes
No
Yes


分析:LCA模版

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N=50002;
vector<int> g[N];
int lv[N];
int p[N][20],S[20];
bool vis[N];
template <class T>
inline void scan_d(T &ret){
	char c;ret=0;
	while((c=getchar())<'0'||c>'9');
	while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}
int max(int a,int b){return a>b?a:b;}
int dfs(int u,int fa,int deep){
	int res=deep,i,v;
	p[u][0]=fa;
	lv[u]=deep;
	vis[u]=1;
	for(i=0;i<g[u].size();i++){
		v=g[u][i];
		if(!vis[v])res=max(res,dfs(v,u,deep+1));
	}
	return res;
}
void init(int n){
	int i,j,level;
	for(S[0]=i=1;i<20;i++)S[i]=S[i-1]<<1;
	memset(vis,0,sizeof(vis));
	memset(p,-1,sizeof(p));
	level=dfs(0,-1,1);
	for(i=1;S[i]<=level;i++)for(j=1;j<=n;j++){
		if(p[j][i-1]!=-1)p[j][i]=p[p[j][i-1]][i-1];
	}
}
int LCA(int x,int y){
	if(lv[x]<lv[y])x^=y,y^=x,x^=y;
	int i,log;
	for(log=0;S[log]<=lv[x];log++);
	for(i=--log;i>=0;i--)if(lv[x]-S[i]>=lv[y])x=p[x][i];
	if(x==y)return x;
	for(i=log;i>=0;i--){
		if(p[x][i]!=-1&&p[x][i]!=p[y][i])x=p[x][i],y=p[y][i];
	}
	return p[x][0];
}
int main(){
	int n,m,ca=1,i,a,b,c,d;
	while(~scanf("%d",&n)){
		if(ca>1)puts("");
		printf("Case %d:\n",ca++);
		for(i=0;i<n;i++)g[i].clear();
		for(i=1;i<n;i++){
			scan_d(a),scan_d(b);
			g[a].push_back(b);
			g[b].push_back(a);
		}
		init(n);
		scanf("%d",&m);
		while(m--){
			scan_d(a),scan_d(b),scan_d(c);
			d=LCA(a,b);
			if(lv[d]<=lv[c]){
				if(LCA(a,c)==c||LCA(b,c)==c){puts("Yes");continue;}
			}
			puts("No");
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值