题解: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 ", (res - a1 + a2 + mod) % mod); } return 0; }