有一个显而易见的道理,一条边,比如说连接的一条边,从出发,如果走偶数次,还是会回到,所以对于每次询问,对于不在最简路径上的边,如果要求至少偶数次,那就走偶数次;奇数次的话,就++。对于最短路径上的,要走奇数次,不然就又回去了。直接查询肯定不好,所以先预处理出整个树的偶数次之和,设为,再减去最简路径的偶数次,加上最简路径的奇数次,处理用lca。

代码如下

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;

const int maxn=100005;
int head[maxn],tot,f[maxn][25],dep[maxn];
ll odd[maxn],eve[maxn],n,m;

struct Edge{
    int v,w,nxt,t;
}e[maxn<<1];

void add(int u,int v,int w,int t)
{
    e[++tot].v=v;
    e[tot].w=w;
    e[tot].t=t;
    e[tot].nxt=head[u];
    head[u]=tot;
}

void dfs(int u,int fa)
{
    dep[u]=dep[fa]+1;
    f[u][0]=fa;
    for(int i=1;(1<<i)<=dep[u];i++)
    f[u][i]=f[f[u][i-1]][i-1];
    for(int i=head[u];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if(v==fa) continue;
        int w=e[i].w;
        int t=e[i].t;
        if(t%2)
        {
            odd[v]=(odd[u]+1LL*t*1LL*w%mod)%mod;
            eve[v]=(eve[u]+1LL*(t+1)*1LL*w%mod)%mod;
        }
        else
        {
            odd[v]=(odd[u]+1LL*(t+1)*1LL*w%mod)%mod;
            eve[v]=(eve[u]+1LL*t*1LL*w%mod)%mod;
        }
        dfs(v,u);
    }
}

int lca(int x,int y)
{
    if(dep[x]>dep[y]) swap(x,y);
    for(int i=20;i>=0;i--) 
    {
        if(dep[y]-(1<<i)>=dep[x])
        y=f[y][i];
    }
    if(x==y) return x;
    for(int i=20;i>=0;i--)
    {
        if(f[x][i]==f[y][i]) continue;
        x=f[x][i];
        y=f[y][i];
    }
    return f[x][0];
}

int main()
{
    scanf("%d",&n);
    ll res=0;
    for(int i=1;i<=n-1;i++)
    {
        int x,y,z,t;
        scanf("%d%d%d%d",&x,&y,&z,&t);
        add(x,y,z,t);
        add(y,x,z,t);
        if(t%2) t++;
        res+=1LL*z*t;
        res%=mod;
    }
    dfs(1,0);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        int l=lca(x,y);
        ll a1=((odd[x]-odd[l]+mod)%mod+(odd[y]-odd[l]+mod)%mod)%mod;
        ll a2=((eve[x]-eve[l]+mod)%mod+(eve[y]-eve[l]+mod)%mod)%mod;
        printf("%lld\n",(res-a2+a1+mod)%mod);
    }
    return 0;
}