列表

详情


NC23981. 寻找

描述

小猫在研究树。
小猫在研究树上的距离。
给定一棵N个点的树,每条边边权为1。
Q次询问,每次给定a,b,c,请你输出a到b的路径上离c最近的点的编号。

输入描述

第一行一个正整数N,表示节点数量。

接下来N−1行,第i行两个正整数ui,vi,表示第i条边连接节点ui,vi。

接下来一行一个正整数Q,表示询问数量。

接下来Q行,每行三个正整数a,b,c,表示一组询问。

输出描述

Q行,每行一个正整数,表示每个询问的答案。

示例1

输入:

5
1 2
1 3
2 4
2 5
3
1 2 3
4 5 1
1 4 5

输出:

1
2
2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 331ms, 内存消耗: 20448K, 提交时间: 2019-04-15 16:06:46

#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
vector<int>e[MAX];
int nex[MAX][21];
int d[MAX];
void dfs(int k,int fa,int dep)
{
    d[k]=dep;
    nex[k][0]=fa;
    for(int i=1;i<=20;i++)nex[k][i]=nex[nex[k][i-1]][i-1];
    for(int i=0;i<e[k].size();i++)
    {
        int nex=e[k][i];
        if(nex==fa)continue;
        dfs(nex,k,dep+1);
    }
}
int LCA(int x,int y)
{
    if(x==y)return x;
    if(d[x]>d[y])swap(x,y);
    for(int i=20;i>=0;i--)
    {
        if(d[x]<d[y]&&d[nex[y][i]]>=d[x])y=nex[y][i];
    }
    for(int i=20;i>=0;i--)
    {
        if(nex[x][i]!=nex[y][i])
        {
            x=nex[x][i];
            y=nex[y][i];
        }
    }
    if(x!=y)return nex[x][0];
    return x;
}
int main(){
	int n;
	scanf("%d",&n);
	int u,v;
	for(int i=0;i<n-1;i++){
		scanf("%d%d",&u,&v);
		e[u].push_back(v);
		e[v].push_back(u);
	} 
	dfs(1,0,1);
	int q;
	scanf("%d",&q);
	while(q--){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		int A=LCA(a,b);
		int B=LCA(a,c);
		int C=LCA(b,c);
		int D=LCA(A,c);
		if(d[D]<d[A])
			printf("%d\n",A);
		else if(d[B]>d[C])
			printf("%d\n",B);
		else printf("%d\n",C);
	}
}

C++11(clang++ 3.9) 解法, 执行用时: 323ms, 内存消耗: 18296K, 提交时间: 2019-04-16 21:53:28

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int dep[N],Fa[N][22],n,q;
vector<int>G[N];
void dfs(int u,int fa) {
	dep[u]=dep[fa]+1;
	Fa[u][0]=fa;
	for(int i=1; (1<<i)<=dep[u]; i++) Fa[u][i]=Fa[Fa[u][i-1]][i-1];
	for(auto &v:G[u]) {
		if(v==fa) continue;
		dfs(v,u);
	}
}
int lca(int x,int y) {
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=20; i>=0; i--) if((1<<i)<=dep[x]-dep[y]) x=Fa[x][i];
	if(x==y) return x;
	for(int i=20; i>=0; i--) if(Fa[x][i]!=Fa[y][i]) x=Fa[x][i],y=Fa[y][i];
	return Fa[x][0];
}
int dis(int x,int y) {
	return dep[x]+dep[y]-2*dep[lca(x,y)];
}
int main(int argc, char const *argv[]) {
	scanf("%d",&n);
	for(int i=0; i<n-1; i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].emplace_back(v);
		G[v].emplace_back(u);
	}
	dfs(1,0);
	scanf("%d",&q);
	while(q--) {
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		int ab=lca(a,b);
		int ac=lca(a,c);
		int bc=lca(b,c);
		int mi=1e9+7;
		mi=min(dep[ac],dep[bc]);
		if(mi<dep[ab]) printf("%d\n", ab);
		else printf("%d\n",dep[c]-dep[ac]<dep[c]-dep[bc] ? ac:bc);
	}
	return 0;
}

上一题