JZOI5257. 小X的佛光

洛谷AC通道!

题目花里胡哨扯一堆,其实就是让我们求两条路径的重合点数。

那么,直接求LCA然后计算即可。  

对于路径 AC, CB, 其重叠路径即为 $(dis[(a、b -> LCA(A, B)] + dis[b、c -> LCA(B, C)] - dis[a、c -> LCA(A, C)]) / 2 + 1$  -> 除以$2$是因为重复计算了路径。加$1$是因为末端点B也算

#include <bits/stdc++.h>
using namespace std;
#define N 1000010

inline int read(){
    int x = 0, s = 1;
    char c = getchar();
    while(!isdigit(c)){
        if(c == '-')s = -1;
        c = getchar();
    }
    while(isdigit(c)){
        x = x * 10 + (c ^ '0');
        c = getchar();
    }
    return x * s;
}

struct node{
    int v, next;
} t[N << 1];
int f[N];

int bian = 0;
inline void add(int u, int v){
    t[++bian] = (node){v, f[u]}, f[u] = bian;
    t[++bian] = (node){u, f[v]}, f[v] = bian;
    return ;
}

int deth[N], siz[N], son[N], fa[N], top[N]; 

#define v t[i].v
void dfs1(int now, int father){
    siz[now] = 1;
    fa[now] = father;
    deth[now] = deth[father] + 1;
    for(int i = f[now]; i; i = t[i].next){
        if(v != father){
            dfs1(v, now);
            siz[now] += siz[v];
            if(siz[v] > siz[son[now]])
                son[now] = v;
        }
    }
    return ;
}

void dfs2(int now, int tp){
    top[now] = tp;
    if(!son[now]) return ;
    dfs2(son[now], tp);
    for(int i = f[now]; i; i = t[i].next){
        if(v != fa[now] && v != son[now])
            dfs2(v, v);
    }
    return ;
}

int lca(int x, int y){
    while(top[x] != top[y]){
        if(deth[top[x]] < deth[top[y]]) swap(x, y);
        x = fa[top[x]];
    }
    return deth[x] > deth[y] ? y : x;
} 


#undef v

int main(){
//    freopen("hh.txt", "r", stdin);
//    freopen("5.txt", "w", stdout);
    int n = read(), T = read(), num = read();
    for(int i = 1;i < n; i++){
        int x = read(), y = read();
        add(x, y);
    }
    if(num != 17 && num != 18){
        dfs1(1, 1);
        dfs2(1, 1);
        while(T--){
            int a = read(), b = read(), c = read();
            int ans1 = abs(2 * deth[lca(a, b)] - deth[b] - deth[a]);
            int ans2 = abs(2 * deth[lca(a, c)] - deth[a] - deth[c]);
            int ans3 = abs(2 * deth[lca(b, c)] - deth[b] - deth[c]);
            printf("%d\n", (ans1  + ans3 - ans2) / 2 + 1);
        }
    }

    else {
        while(T--){
            int a = read(), b = read(), c = read();
            if((a < b && c > b) || (c < b && a > b)) puts("1");
            else {
                printf("%d\n", min(abs(b - a), abs(c - b)) + 1) ;
            }
        } 
    }
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wondering-world/p/13373765.html