这道题很卡常
但用一些优化 可过
问题
求一点到 三个不同点的距离最小
输出这个点 和这个距离
#define sum(a,b,c) (depth[a] + depth[b] + depth[c])
t,ab = lca(a,b),ac = lca(a,c),bc = lca(b,c);
if(ab == ac) t = bc;
if(ab == bc) t = ac;
if(ac == bc) t = ab;
printf("%d %d
",t,sum(a,b,c) - sum(ab,ac,bc));
感性理解下
倍增的一些优化
for(reg i = 1;i <= n;i++)
lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
inline int lca(int a,int b)
{
if(depth[a] < depth[b]) swap(a,b);
while(depth[a] > depth[b]) a = fa[a][lg[depth[a] - depth[b]] - 1];
if(a == b) return a;
for(reg i = lg[depth[a]];i >= 0;i--)
if(fa[a][i] != fa[b][i])
a = fa[a][i],b = fa[b][i];
return fa[a][0];
}
总结
-
少函数,非递归函数用宏
-
(lca),提前处理(log)
-
register int
-
变量名尽量小写,短
(Code)
#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
#define reg register int
const int MAXN = 5e5 + 10;
int cnt,fa[MAXN][30],lg[MAXN],head[MAXN],depth[MAXN],n,m;
bool vis[MAXN];
struct node
{
int v,next;
}edge[MAXN << 1];
template<typename T>
inline T Read(T Type)
{
T x = 0;
bool f = 0;
char a = getchar();
while(!isdigit(a)) {if(a == '-') f = 1;a = getchar();}
while(isdigit(a)) x = (x << 1) + (x << 3) + a - '0',a = getchar();
if(f) x *= -1;
return x;
}
inline void addedge(int u,int v)
{
edge[++cnt].v = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
inline void prepare(int x)
{
vis[x] = 1;
for(reg i = head[x];i;i = edge[i].next)
{
int v = edge[i].v;
if(vis[v]) continue;
fa[v][0] = x;
depth[v] = depth[x] + 1;
prepare(v);
}
}
inline int lca(int a,int b)
{
if(depth[a] < depth[b]) swap(a,b);
while(depth[a] > depth[b]) a = fa[a][lg[depth[a] - depth[b]] - 1];
if(a == b) return a;
for(reg i = lg[depth[a]];i >= 0;i--)
if(fa[a][i] != fa[b][i])
a = fa[a][i],b = fa[b][i];
return fa[a][0];
}
#define sum(a,b,c) (depth[a] + depth[b] + depth[c])
int main()
{
n = Read(1),m = Read(1);
for(reg i = 1;i < n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v),addedge(v,u);
}
fa[1][0] = 1;
for(reg i = 1;i <= n;i++)
lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
prepare(1);
for(reg i = 1;i <= lg[n];i++)
for(reg j = 1;j <= n;j++)
fa[j][i] = fa[fa[j][i - 1]][i - 1];
int t,a,b,c,ab,ac,bc;
for(reg i = 1;i <= m;i++)
{
a = Read(1),b = Read(1),c = Read(1),t,ab = lca(a,b),ac = lca(a,c),bc = lca(b,c);
if(ab == ac) t = bc;
if(ab == bc) t = ac;
if(ac == bc) t = ab;
printf("%d %d
",t,sum(a,b,c) - sum(ab,ac,bc));
}
return 0;
}