CF-div2-620-E. 1-Trees and Queries LCA 树上点距离

思路

树链剖分求出LCA
用LCA求两点之间距离(借助到根的距离):depth[x] + depth[y] - 2*depth[LCA];
加边后a,b两点可以保持距离为k的条件: k>=改变后的距离; 改变后的距离刚好等于k,如果不等那么距离相差偶数,来回走来走去就能走到走凑成k

考虑加边对a,b距离的影响;有三种情况
1.加边后,不影响a,b
2.a先到x,x再走到y(这里新加的边,距离为1),y再走到b
3.a先到y,y再走到x(+1),x再走到b

判断最终距离<=k,并且相差为偶数

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+100;
vector<int> g[maxn];
ll fa[maxn],depth[maxn],sz[maxn],son[maxn],id[maxn],rk[maxn],top[maxn],bot[maxn];
int cnt = 0;
int n,q,root = 1;

/*
树链剖分求LCA
LCA求两点之间距离(借助到根的距离):depth[x] + depth[y] - 2*depth[LCA];
可以保持距离为k的条件: k>=改变后的距离; 改变后的距离刚好等于k,如果不等那么距离相差偶数,来回走来走去就能走到走凑成k
*/

void dfs(int x,int deep){
	depth[x] = deep;
	sz[x] = 1;
	for(int li = 0;li<g[x].size();li++){
		int i = g[x][li];
		if(i == fa[x]) continue;
		fa[i] = x;
		dfs(i,deep+1);
		sz[x] += sz[i];
		if(sz[i] > sz[son[x]]) son[x] = i;
	}
}

void dfs2(int x,int tp){
	top[x] = tp;
	id[x] = ++cnt;
	rk[cnt] = x;
	if(son[x]) dfs2(son[x],tp),bot[x] = bot[son[x]];
	else bot[x] = x;
	for(int li=0;li<g[x].size();li++){
		int i = g[x][li];
		if(i != fa[x] && i != son[x])
			dfs2(i,i);
	}
}

int lca(int u,int v){
	while(top[u] != top[v]){
		if(depth[top[u]] < depth[top[v]]) swap(u,v);
		u = fa[top[u]];
	}
	if(depth[u] < depth[v]) return u;
	return v;
}

//求两点之间的简单路径距离 
ll dis(int x,int y){
	int LCA = lca(x,y);
	return depth[x] + depth[y] - 2*depth[LCA];
}

int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n-1;i++){
		ll u,v;
		cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(root,1);
	dfs2(root,root);
	cin>>q;
	while(q--){
		ll x,y,a,b,k;
		cin>>x>>y>>a>>b>>k;
		ll ans = 0x3f3f3f3f;
		//a,b两点与x,y有三种关系
		ll dist1 = dis(a,b); //无关 
		ll dist2 = dis(a,x) + dis(y,b) + 1; //a先到x,x再走到y(这里新加的边,距离为1),y再走到b 
		ll dist3 = dis(a,y) + dis(x,b) + 1;
		bool flag = false;
		if((k - dist1)%2 == 0 && dist1 < ans) ans = dist1;
		if((k - dist2)%2 == 0 && dist2 < ans) ans = dist2;
		if((k - dist3)%2 == 0 && dist3 < ans) ans = dist3;
		if(ans <= k) flag = true;
		if(flag) puts("YES");
		else puts("NO");
	}
	return 0;
}
/*
5
1 2
2 3
3 4
4 5
5
1 3 1 2 2
1 4 1 3 2
1 4 1 3 3
4 2 3 3 9
5 2 3 3 9
*/
原文地址:https://www.cnblogs.com/fisherss/p/12385121.html