题目描述:
Y 岛风景美丽宜人,气候温和,物产丰富。
Y 岛上有 N 个城市(编号 1,2,…,N),有 N−1 条城市间的道路连接着它们。
每一条道路都连接某两个城市。
幸运的是,小可可通过这些道路可以走遍 Y 岛的所有城市。
神奇的是,乘车经过每条道路所需要的费用都是一样的。
小可可,小卡卡和小 YY 经常想聚会,每次聚会,他们都会选择一个城市,使得 3 个人到达这个城市的总费用最小。
由于他们计划中还会有很多次聚会,每次都选择一个地点是很烦人的事情,所以他们决定把这件事情交给你来完成。
他们会提供给你地图以及若干次聚会前他们所处的位置,希望你为他们的每一次聚会选择一个合适的地点。
输入格式
第一行两个正整数,N 和 M,分别表示城市个数和聚会次数。
后面有 N−1 行,每行用两个正整数 A 和 B 表示编号为 A 和编号为 B 的城市之间有一条路。
再后面有 M 行,每行用三个正整数表示一次聚会的情况:小可可所在的城市编号,小卡卡所在的城市编号以及小 YY 所在的城市编号。
输出格式
一共有 M 行,每行两个数 Pos 和 Cost,用一个空格隔开,表示第 i 次聚会的地点选择在编号为 Pos 的城市,总共的费用是经过 Cost 条道路所花费的费用。
数据范围
N≤500000,M≤500000
输入样例:
6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6
输出样例:
5 2
2 5
4 1
6 0
思路:
- a,b,c三点的最近祖先一定是lca(a,b),lca(a,c),lca(b,c)中的一个
- 要用printf不要用cout,超时了十多次原来是因为这个
代码:
// https://ac.nowcoder.com/acm/problem/50472
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N = 500010, M = N * 2;
int h[N], e[M], ne[M], idx;
int depth[N], fa[N][20];
inline int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c>'9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void bfs(int root)
{
queue<int>q;
q.push(root);
depth[root] = 1;
depth[0] = 0;
while (!q.empty())
{
int t = q.front();
q.pop();
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (depth[j] > depth[t] + 1)
{
depth[j] = depth[t] + 1;
fa[j][0] = t;
q.push(j);
for (int k = 1; k < 19; k++)
{
fa[j][k] = fa[fa[j][k - 1]][k - 1];
}
}
}
}
}
inline void add(int a, int b )
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
inline int lca(int u, int v)
{
if (depth[u] < depth[v])
{
swap(u, v);
}
for (int k = 18; k >= 0; k--)
{
if (depth[fa[u][k]] >= depth[v])
{
u = fa[u][k];
}
}
if (u == v)
{
return u;
}
for (int k = 18; k >= 0; k--)
{
if (fa[u][k] != fa[v][k])
{
u = fa[u][k];
v = fa[v][k];
}
}
return fa[u][0];
}
inline pair<int,int> f(int a, int b,int c)
{
pair<int, int>res(0,0);
int t=lca(a, b);
res.second = t;
res.first += depth[a] + depth[b] - depth[t] * 2;
res.first += depth[t] + depth[c] - depth[lca(t,c)] * 2;
return res;
}
int main()
{
memset(h, -1, sizeof h);
memset(depth, 0x3f, sizeof depth);
int n,m;
cin >> n >> m;
int root = 0;
for (int i = 0; i < n - 1; i++)
{
int a, b;
a = read();
b = read();
add(a, b );
add(b, a );
}
root = 1;
bfs(root);
while (m--)
{
int a, b ,c;
a = read();
b = read();
c = read();
pair<int, int> t = min(f(a, b, c), min(f(b, c, a), f(a, c, b)));
printf("%d %d\n", t.second, t.first);
}
}