城市漫游-牛客

题解:u - v这条简单路径上的边会经过奇数次,其余的边会经过偶数次,因为从简单路径中的点出去后还得回来。直接算的话每次询问都得搜整棵树,显然效率是极其低的。如果先预处理出整棵树的边都经过偶数次的花费V,那么答案就等于 V — 简单路径中的边经过偶数次的花费 + 简单路径中的边经过奇数次的代价。下一步是得到后两项,借助LCA,维护路径的前缀和就ok了。

注意取模!!!!!!

#include<bits/stdc++.h>
#define ll long long
#define P pair<int,int>
#define pb push_back
#define lson root << 1
#define INF (int)2e9 + 7
#define maxn (int)1e5 + 7
#define rson root << 1 | 1
#define LINF (unsigned long long int)1e18
#define mem(arry, in) memset(arry, in, sizeof(arry))
using namespace std;

const ll mod = 1000000007;

int n, m, tot;
int head[maxn], pa[maxn][20], d[maxn];
ll odd[maxn], even[maxn];

struct node{
    int to, next, va, t;
}g[maxn << 1];

void Inite()
{
    tot = 0;
    mem(pa, -1);
    mem(head, -1);
}

void addedge(int u, int v, int w, int t){
    g[tot].t = t;
    g[tot].to = v;
    g[tot].va = w;
    g[tot].next = head[u];
    head[u] = tot++;
}

void DFS(int u, int p){
    pa[u][0] = p;
    for(int i = head[u]; i != -1; i = g[i].next){
        int v = g[i].to;
        if(v == p) continue;
        d[v] = d[u] + 1;

        int t = g[i].t;
        int w = g[i].va;
        if(t % 2){
            odd[v] = (odd[u] + (ll)t * (ll)w % mod) % mod;
            even[v] = (even[u] + (ll)(t + 1) * (ll)w % mod) % mod;
        }
        else{
            odd[v] = (odd[u] + (ll)(t + 1) * (ll)w % mod) % mod;
            even[v] = (even[u] + (ll)t * (ll)w % mod) % mod;
        }
        DFS(v, u);
    }
}

void compute(){
    DFS(1, -1);
    for(int i = 1; (1 << i) <= n; i++) {
        for(int j = 1; j <= n; j++) if(pa[j][i - 1] != -1) {
            pa[j][i] = pa[pa[j][i - 1]][i - 1];
        }
    }
}

int Lct(int u, int v){
    if(d[u] > d[v]) swap(u, v);
    for(int i = 0; i < 20; i++) {
        if(((d[v] - d[u]) >> i) & 1) v = pa[v][i];
    }
    if(u == v) return u;
    for(int i = 19; i >= 0; i--) {
        if(pa[u][i] != pa[v][i]){
            u = pa[u][i];
            v = pa[v][i];
        }
    }
    return pa[u][0];
}

int main()
{
    Inite();
    scanf("%d", &n);

    ll res = 0;
    for(int i = 1; i < n; i++) {
        int x, y, z, t;
        scanf("%d %d %d %d", &x, &y, &z, &t);
        addedge(x, y, z, t);
        addedge(y, x, z, t);
        if(t % 2) t++;
        res += (ll)t * (ll)z;
        res %= mod;
    }

    compute();

    scanf("%d", &m);
    for(int i = 0; i < m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        int p = Lct(u, v);

        ll a1 = ((even[u] - even[p] + mod) % mod + (even[v] - even[p] + mod) % mod) % mod;
        ll a2 = ((odd[u] - odd[p] + mod) % mod + (odd[v] - odd[p] + mod) % mod) % mod;
        printf("%lld\n", (res - a1 + a2 + mod) % mod);
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zgglj-com/p/9219204.html