题目描述
Windy 和 Zero 居住在同一个国家,该国家有N个城市。Windy 居住在 X 城市,Zero 居住在 Y 城市。任意两个城市之间有且只有一条路径相通(中间可能经过其它城市)。有一天,Windy 和 Zero 想见面,他们想把见面的地点定在城市 X 和城市 Y 的中间。现在请你告诉他们会见地点应该在哪里?
输入格式
第一行是一个整数 N(1≤N≤10 000),表示有 N 个城市。
接下来有 N-1 行,每行有两个整数 A,B,表示有一条路直接连接城市 A 和城市 B。
(1≤A,B≤N)
接下来有一个整数 M(1≤M≤100 000),表示下面有 M 个询问。
接下来有 M 行,每行有两个整数 X,Y,表示 Windy 和 Zero 居住的城市编号。
(1≤X,Y≤N)
输出格式
对于每个询问,如果城市 X 和城市 Y 的中点在一个城市上,则输出该中点城市的编号;如果这个中点在某条路径上,则输出这条路径两个端点的城市编号(用一个空格隔开),并且首先输出离城市X近的城市的编号。
样例数据 1
输入 [复制]
6
1 2
2 3
2 4
4 5
6 4
3
5 3
3 5
6 5
输出
4 2
2 4
4
Windy 和 Zero 居住在同一个国家,该国家有N个城市。Windy 居住在 X 城市,Zero 居住在 Y 城市。任意两个城市之间有且只有一条路径相通(中间可能经过其它城市)。有一天,Windy 和 Zero 想见面,他们想把见面的地点定在城市 X 和城市 Y 的中间。现在请你告诉他们会见地点应该在哪里?
输入格式
第一行是一个整数 N(1≤N≤10 000),表示有 N 个城市。
接下来有 N-1 行,每行有两个整数 A,B,表示有一条路直接连接城市 A 和城市 B。
(1≤A,B≤N)
接下来有一个整数 M(1≤M≤100 000),表示下面有 M 个询问。
接下来有 M 行,每行有两个整数 X,Y,表示 Windy 和 Zero 居住的城市编号。
(1≤X,Y≤N)
输出格式
对于每个询问,如果城市 X 和城市 Y 的中点在一个城市上,则输出该中点城市的编号;如果这个中点在某条路径上,则输出这条路径两个端点的城市编号(用一个空格隔开),并且首先输出离城市X近的城市的编号。
样例数据 1
输入 [复制]
6
1 2
2 3
2 4
4 5
6 4
3
5 3
3 5
6 5
输出
4 2
2 4
4
-------------------------------------------------------------------------------------------------------
思路很简单 可以看出给出的图是一棵树 要找两个点之间的中点 相当于找他们之间的距离 然后除以二 通过其中一个点往上爬这样的距离
但是有几点细节
1.在我们从一个点往上找离这个点距离d的点时候 可以会用到一个函数
我们姑且命名其为get_pos
在写get_pos的时候...
2.在询问两点的时候 我们设置一个函数query
注意 如果距离%2==0 那么说明只有一个中点 不会出现两个
这个时候 不能直接输出这两个点的lca(我卡了很久)
然后看代码吧
#include<bits/stdc++.h>
using namespace std;
int n,m,tot;
struct node
{
int next;
int to;
}edge[2*10005];
int first[10005],deepth[10005],fa[10005][20];
inline void add(int x,int y)
{
++tot;
edge[tot].to=y;
edge[tot].next=first[x];
first[x]=tot;
}
void dfs(int now,int father)
{
deepth[now]=deepth[father]+1;
fa[now][0]=father;
for(int i=1;(1<<i)<=deepth[now];i++)
{
fa[now][i]=fa[fa[now][i-1]][i-1];
}
for(int i=first[now];i;i=edge[i].next)
{
int vis=edge[i].to;
if(vis!=father) dfs(vis,now);
}
}
int lca(int x,int y)
{
if(deepth[x]<deepth[y]) swap(x,y);
for(int i=17;i>=0;i--)
{
if(deepth[fa[x][i]]>=deepth[y]) x=fa[x][i];
}
if(x==y) return x;
for(int i=17;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
int get_pos(int u,int d)
{
//注意一定要新定义一个 不然你会gg
int a=u;
//get u往上面d距离的点
for(int i=17;i>=0;i--)
{
if(deepth[u]-deepth[fa[a][i]]<=d) a=fa[a][i];
}
return a;
}
void query(int x,int y)
{
int ancestor=lca(x,y);
// cout<<
int d=deepth[x]+deepth[y]-2*deepth[ancestor];
if(d%2==0)
{
cout<<get_pos((deepth[x]>deepth[y]?x:y),d/2)<<endl;
}
else
{
if(deepth[x]>deepth[y])
{
int pos=get_pos(x,d/2);
cout<<pos<<" ";
cout<<fa[pos][0]<<endl;
}
else
{
int pos=get_pos(y,d/2);
cout<<fa[pos][0]<<" "<<pos<<endl;
}
}
}
int main()
{
//freopen("wordin.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
scanf("%d",&m);
dfs(1,0);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
query(x,y);
}
return 0;
}