luoguP4281[AHOI2008]紧急集合 / 聚会

最近复习lca,布置的三道题中最后一道就是这个紫题。当时看到是紫题吓了一跳(果然是我太弱了QAQ)然后仔细读了几遍题,发现这就是普通的lca嘛 (太水了) 其中变化的只有要分别求三者的lca。

#include<cstdio>
#include<algorithm>
#include<iostream> 
#include<cstring>
using namespace std;
typedef long long ll;
struct kh{
    int t, nxt;
}e[2*500001];
int dep[500001], f[500001][22], tot, head[500001], lo[500001], t;
ll ans = 0;
void add(int x,int y)
{
     e[++tot].t = y; 
    e[tot].nxt = head[x];
    head[x] = tot;
}
void dfs(int fa, int h)
{
    dep[fa] = dep[h] + 1;
    f[fa][0] = h;
    for(int i = 1;(1<<i) <= dep[fa];i++)
      f[fa][i] = f[f[fa][i-1]][i-1];
    for(int i = head[fa];i;i = e[i].nxt)
      if(e[i].t != h)
        dfs(e[i].t,fa);
}
int lca(int x,int y)
{
    if(dep[x] < dep[y])
      swap(x,y);
    while(dep[x] > dep[y])
      x = f[x][lo[dep[x] - dep[y]] - 1];
    if(x == y)
      return x;
    for(int k= lo[dep[x]] - 1;k >= 0;k--)
      if(f[x][k] != f[y][k])
        x = f[x][k], y = f[y][k];
    return f[x][0];
}
int n, m, s, x, y, a, b, c;
int main()
{
    scanf("%d %d", &n, &m);
    for(int i = 1;i <= n - 1;i++)
    {
        scanf("%d %d", &a, &b);
        add(a, b);
        add(b, a);
    }
    dfs(1,0);
    for(int i = 1;i <= n;i++)
    lo[i] = lo[i - 1] + (1<<lo[i - 1] == i);
    for(int i = 1;i <= m;i++)
    {
        ans = 0;
        scanf("%d %d %d", &a, &b, &c);
        int t1 = lca(a,b);//分别求三者lca
        int t2 = lca(a,c);
        int t3 = lca(b,c);
        if(t1 == t2)
        t = t3;
        else if(t1 == t3)
        t = t2;
        else if(t2 == t3)
        t = t1;
        ans = dep[a] + dep[b] + dep[c] - dep[t1] - dep[t2] - dep[t3];
        printf("%d %lld\n", t, ans);
    }
    return 0;
}

 

posted @ 2019-03-30 18:22  机器闵  阅读(116)  评论(0编辑  收藏  举报