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