1-Trees and Queries(lca/思维)

题目:http://codeforces.com/contest/1304/problem/E
参考:https://www.cnblogs.com/CADCADCAD/p/12321407.html
题意:给定一棵树,多次询问,每次询问,再添加了x到y的边后,从a到b是否有一长度为k的路径,这里路径允许重复经过点和树边。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;

int n;
struct edge{
	int v,nxt;
}e[maxn<<1];
int tot,head[maxn];
void addedge(int u,int v) {
	e[tot].v = v;
	e[tot].nxt = head[u];
	head[u] = tot++;
}
void init() {
	tot = 0;
	memset(head,-1,sizeof(head));
}
int dep[maxn],sz[maxn],son[maxn],f[maxn];
int top[maxn];
void dfs1(int u,int fa,int deep) {
	dep[u] = deep,f[u] = fa,sz[u] = 1;
	int mxson = -1;
	for(int i = head[u];~i;i = e[i].nxt) {
		int v = e[i].v;
		if(v == fa) continue;
		dfs1(v,u,deep+1);
		sz[u] += sz[v];
		if(sz[v] > mxson) mxson = sz[v],son[u] = v;
	}
}
void dfs2(int u,int fr) {
	top[u] = fr;
	if(son[u]) dfs2(son[u],fr);
	for(int i = head[u];~i;i = e[i].nxt) {
		int v = e[i].v;
		if(v == son[u] || v == f[u]) continue;
		dfs2(v,v);
	}
}
int dis(int x,int y) {
	int ans = dep[x]+dep[y];
	while(top[x] != top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x,y);
		x = f[top[x]];
	}
	if(dep[x] > dep[y]) swap(x,y);
	ans -= 2*dep[x];
	return ans;
}
bool Check(int &d,int &k) {
	return d <= k && (d%2 == k%2);
}
int main() {
	scanf("%d",&n);
	init();
	for(int i = 1,u,v;i < n;i++) {
		scanf("%d%d",&u,&v);
		addedge(u,v);addedge(v,u);
	} 
	dfs1(1,1,0);dfs2(1,1);
	int q;scanf("%d",&q);
	while(q--) {
		int x,y,a,b,k;
		scanf("%d%d%d%d%d",&x,&y,&a,&b,&k);
		bool ok = 0;
		int ab = dis(a,b);
		int ax = dis(a,x),ay = dis(a,y);
		int bx = dis(b,x),by = dis(b,y);
		int d1 = ax+by+1,d2 = ay+bx+1;
		if(Check(ab,k) || Check(d1,k) || Check(d2,k))
			puts("YES");
		else
			puts("NO");
	} 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值