BZOJ
Description
Y岛风景美丽宜人,气候温和,物产丰富。Y岛上有N个城市,有N-1条城市间的道路连接着它们。每一条道路都连接某两个城市。幸运的是,小可可通过这些道路可以走遍Y岛的所有城市。神奇的是,乘车经过每条道路所需要的费用都是一样的。小可可,小卡卡和小YY经常想聚会,每次聚会,他们都会选择一个城市,使得3个人到达这个城市的总费用最小。 由于他们计划中还会有很多次聚会,每次都选择一个地点是很烦人的事情,所以他们决定把这件事情交给你来完成。他们会提供给你地图以及若干次聚会前他们所处的位置,希望你为他们的每一次聚会选择一个合适的地点。
Input
第一行两个正整数,N和M。分别表示城市个数和聚会次数。后面有N-1行,每行用两个正整数A和B表示编号为A和编号为B的城市之间有一条路。城市的编号是从1到N的。再后面有M行,每行用三个正整数表示一次聚会的情况:小可可所在的城市编号,小卡卡所在的城市编号以及小YY所在的城市编号。
Output
一共有M行,每行两个数Pos和Cost,用一个空格隔开。表示第i次聚会的地点选择在编号为Pos的城市,总共的费用是经过Cost条道路所花费的费用。
Sample Input
6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6
Sample Output
5 2
2 5
4 1
6 0
数据范围:
100%的数据中,N<=500000,M<=500000。
40%的数据中N<=2000,M<=2000。
题解:
没什么特别好的思路,感觉我就是暴力。。。
嗯,就是把三个点两两的LCA = t找出来,然后找出t与第三个点的LCA,然后计算长度,嗯,三个长度都算出来了,之后比较三个长度的长短,输出最短的。就算用的倍增找LCA,而且思路感觉有点偷懒,最后还是成功AC,且在BZOJ排在100名,还可以。
代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 500005;
int N,M,MAXD,e = 1;
int head[MAXN],deep[MAXN],anc[MAXN][25];
inline int abs(int x){ return x > 0 ? x : -x; }
struct node{
int v,next;
}edge[MAXN*2];
inline void addedge(int u,int v){
edge[e] = (node){v,head[u]};head[u] = e++;
edge[e] = (node){u,head[v]};head[v] = e++;
}
inline int read(){
int x = 0;char ch = getchar();
while(ch < '0' || '9' < ch) {ch = getchar();}
while('0' <= ch&& ch <='9') {x = x * 10 +ch-'0';ch = getchar();}
return x;
}
inline void init(){
N = read();M = read();
for(int i = 1;i < N;i <<= 1,MAXD++);
int u,v;
for(int i = 1;i < N;i++){
u = read();v = read();
addedge(u,v);
}
}
void dfs(int u,int h){
deep[u] = h;
for(int i = 1;i <= MAXD;i++) anc[u][i] = anc[ anc[u][i-1] ][i-1];
for(int i = head[u];i;i = edge[i].next){
int v = edge[i].v;
if(!deep[v]){
anc[v][0] = u;
dfs(v,h+1);
}
}
}
inline void swim(int &u,int h){
for(int i = 0;h;i++){
if(h&1) u = anc[u][i];
h >>= 1;
}
}
inline int query(int u,int v){
if(deep[u] < deep[v]) swap(u,v);
swim(u,deep[u] - deep[v]);
if(u == v) return u;
for(int i = MAXD;i >= 0;i--)
if(anc[u][i] != anc[v][i]){
u = anc[u][i];
v = anc[v][i];
}
if(u != v) return anc[u][0];
return u;
}
int main(){
init();
dfs(1,1);
int a,b,c,lca_a_b,lca_b_c,lca_a_c,lca_1,lca_2,lca_3,dist1,dist2,dist3;
for(int i = 1;i <= M;i++)
{
a = read();b = read();c = read();
lca_a_b = query(a,b);lca_b_c = query(b,c);lca_a_c = query(a,c);
lca_1 = query(lca_a_b,c);lca_2 = query(lca_b_c,a);lca_3 = query(lca_a_c,b);
dist1 = abs(deep[lca_a_b] - deep[a]) + abs(deep[lca_a_b] - deep[b]) + abs(deep[lca_1] - deep[c]) + abs(deep[lca_1] - deep[lca_a_b]);
dist2 = abs(deep[lca_b_c] - deep[b]) + abs(deep[lca_b_c] - deep[c]) + abs(deep[lca_2] - deep[a]) + abs(deep[lca_1] - deep[lca_b_c]);
dist3 = abs(deep[lca_a_c] - deep[a]) + abs(deep[lca_a_c] - deep[c]) + abs(deep[lca_3] - deep[b]) + abs(deep[lca_1] - deep[lca_a_c]);
if(dist1 > dist2){
if(dist2 > dist3) printf("%d %d\n",lca_a_c,dist3);
else printf("%d %d\n",lca_b_c,dist2);
}
else {
if(dist1 > dist3) printf("%d %d\n",lca_a_c,dist3);
else printf("%d %d\n",lca_a_b,dist1);
}
}
return 0;
}