完整代码:


#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 5e4 + 10;

struct Query{
    int id, u, v, c;
}querys[N];

bool cmp(Query q1, Query q2){
    if(q1.c == q2.c) return q1.id < q2.id;
    return q1.c < q2.c;
}

int n, m, lg[2*N], dep[N], fa[N][18], dis[N][18], ans[N], len[N], g[N][18];
vector<pii> e[N];

void dfs(int u, int father){
    dep[u] = dep[father] + 1;
    fa[u][0] = father;
    for(int i = 1; i <= lg[dep[u]]; i ++){
        fa[u][i] = fa[fa[u][i-1]][i-1];
        dis[u][i] = dis[u][i - 1] + dis[fa[u][i-1]][i-1];
    }
    for(int i = 0; i < (int)e[u].size(); i ++){
        int v = e[u][i].first, w = e[u][i].second;
        if(v == father) continue;
        dis[v][0] = w;
        len[v] = len[u] + w;
        dfs(v, u);
    }
}

int lca(int x, int y){
    if(dep[x] < dep[y]) swap(x, y);
    while(dep[x] > dep[y]){
        int h = dep[x] - dep[y];
        x = fa[x][lg[h]];
    }
    if(x == y) return x;
    for(int i = lg[dep[x]]; i >= 0; i --){
        if(fa[x][i] != fa[y][i]){
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}

int getlen(int u, int v, int LCA){
    if(LCA == -1) LCA = lca(u, v);
    return len[u] + len[v] - 2*len[LCA];
}

int jump1(int u, int v, int c){
    int LCA = lca(u, v), cnt = 0, lastu = 0, lastv = 0;
    while(1){
        cnt++;
        lastu = u;
        int rest = c;
        for(int i = lg[dep[u]]; i >= 0; i --){
            if(rest >= dis[u][i]){
                rest -= dis[u][i];
                u = fa[u][i];
            }
        }
        if(dep[u] <= dep[LCA]){
            cnt--;
            u = lastu;
            break;
        }
    }
    while(1){
        cnt++;
        lastv = v;
        int rest = c;
        for(int i = lg[dep[v]]; i >= 0; i --){
            if(rest >= dis[v][i]){
                rest -= dis[v][i];
                v = fa[v][i];
            }
        }
        if(dep[v] <= dep[LCA]){
            cnt--;
            v = lastv;
            break;
        }
    }
    if(u == LCA && v == LCA) return cnt;
    else if(c >= getlen(u, v, LCA)) return cnt+1;
    else return cnt+2;
}

void init_g(int c){
    memset(g, 0, sizeof(g));
    for(int j = 1; j <= n; j ++){
        int x = j, rest = c;
        for(int k = lg[dep[j]]; k >= 0; k --){
            if(rest >= dis[x][k]){
                rest -= dis[x][k];
                x = fa[x][k];
            }
        }
        g[j][0] = x;
        for(int k = 1; k <= lg[dep[j]]; k ++){
            g[j][k] = g[g[j][k-1]][k-1];
        }
    }
}

int jump2(int u, int v, int c){
    int LCA = lca(u, v), cnt = 0;
    for(int i = lg[dep[u]]; i >= 0; i --){
        int nxt = g[u][i];
        if(dep[nxt] > dep[LCA]){
            cnt += (1<<i);
            u = nxt;
        }
    }
    for(int i = lg[dep[v]]; i >= 0; i --){
        int nxt = g[v][i];
        if(dep[nxt] > dep[LCA]){
            cnt += (1<<i);
            v = nxt;
        }
    }
    if(u == LCA && v == LCA) return cnt;
    else if(c >= getlen(u, v, LCA)) return cnt+1;
    else return cnt+2;
}

int jump3(int u, int v, int c){
    int LCA = lca(u, v), cnt = 0;
    for(int i = lg[dep[u]]; i >= 0; i --){
        int nxt = g[u][i];
        if(dep[nxt] >= dep[LCA]){
            cnt += (1<<i);
            u = nxt;
        }
    }
    for(int i = lg[dep[v]]; i >= 0; i --){
        int nxt = g[v][i];
        if(dep[nxt] >= dep[LCA]){
            cnt += (1<<i);
            v = nxt;
        }
    }
    if(u == LCA && v == LCA) return cnt;
    else if(c >= getlen(u, v, LCA)) return cnt+1;
    else return cnt+2;
}

int main(){
    freopen("tree.in", "r", stdin);
    freopen("tree.out", "w", stdout);
    ios::sync_with_stdio(0);
    
    for(int i = 2; i <= 2*N - 10; i ++) lg[i] = lg[i>>1] + 1;
    cin >> n;
    for(int i = 1; i < n; i ++){
        int x, y, z;
        cin >> x >> y >> z;
        e[x].push_back({y, z});
        e[y].push_back({x, z});
    }
    dfs(1, 0);

    //将查询离线下来
    cin >> m;
    for(int i = 1; i <= m; i ++){
        int u, v, c;
        cin >> u >> v >> c;
        querys[i] = {i, u, v, c};
    }
    sort(querys + 1, querys + m + 1, cmp);

    int lastc = 0, Sqrt = (int)floor(sqrt(2*n));
    for(int i = 1; i <= m; i ++){
        int id = querys[i].id, u = querys[i].u, v = querys[i].v, c = querys[i].c;
        
        if(c > Sqrt){//暴力倍增解决
            ans[id] = jump1(u, v, c);
        }else{//否则查表倍增解决
            
            if(lastc != querys[i].c){//处理一个新的表,覆盖上一个表
                //处理表的总复杂度sqrt(2n)*n*log n,实际至少折成1/4吧
                init_g(c);
            }
            //倍增解决
            ans[id] = jump2(u, v, c);
        }
        
        lastc = c;
    }
    for(int i = 1; i <= m; i ++) cout << ans[i] << "\n";
    return 0;
}

其中,void jump2() 是正确的,void jump3() 是错误的。它们的区别就在于大于号和大于等于号。

为什么?【未完待续】

0 条评论

目前还没有评论...

信息

ID
2807
时间
ms
内存
MiB
难度
7
标签
(无)
递交数
47
已通过
5
上传者