这题需要大量的lca,预处理是可以,但是会写死,因此采用rmq。
先学会如何求两个路径[a,b],[c,d]的交。
只要分别求c,d到[a,b]距离最近的点[u,v],然后判u,v是否在[c,d]上即可。下面以用c求u为例。
r<-lca(a,b)
if lca(r,c)!=r then u<-r
else if lca(a,c)!=r then u<-lca(a,c)
else u<-lca(b,c)
然后检验。
r<-lca(c,d)
u∈[c,d]当且仅当u在r的子树中(lca(u,r)==r)且lca(c,u)与lca(d,u)中有一个为u
同理求出并检验v
然后分类讨论。设s1、t1为[a,b]上的那个人到达、离开[u,v]的时间,s2、t2同理。
然后由于这些数是浮点数(被v除过了),精度抖来抖去很麻烦,就把分母都乘到对面去,但要记得开long long !
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<bitset>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define sqr(x) ((x)*(x))
#define G getchar()
#define LL long long
#define pii pair<int,int>
#define mkp make_pair
#define X first
#define Y second
#define N 100005
#define NN 1005
#define inf 10000000
LL n,m,A[NN],B[NN],V[NN],ans;
LL he[N],ne[N<<1],W[N<<1],to[N<<1],tot;
LL lg[N<<1],dep[N],deep[N],phi[N<<1],id,pos[N],Min[N<<1][20];
LL read(){
LL x=0;char ch=G;bool flg=0;
while((ch<48||ch>57)&&ch!=45)ch=G;
if(ch==45)flg=1,ch=G;
for(;ch>47&&ch<58;ch=G)x=x*10+ch-48;
return flg?-x:x;
}
void add(LL x,LL y,LL z){
to[++tot]=y;W[tot]=z;ne[tot]=he[x];he[x]=tot;
}
void DFS(LL x,LL e){
LL y,i;dep[phi[pos[x]=++id]=x]=dep[to[e]]+1;
for(i=he[x];i;i=ne[i])if(i!=e){
deep[y=to[i]]=deep[x]+W[i];DFS(y,i^1);phi[++id]=x;
}
}
LL les(LL x,LL y){
return dep[x]<dep[y]?x:y;
}
LL rmq(LL x,LL y){
x=pos[x];y=pos[y];if(x>y)swap(x,y);
LL tmp=lg[y-x+1];
return les(Min[x][tmp],Min[y-(1<<tmp)+1][tmp]);
}
LL getd(LL x,LL y){
return deep[x]+deep[y]-(deep[rmq(x,y)]<<1);
}
bool check(LL x,LL y){
LL z1=rmq(A[x],B[x]),z2=rmq(A[y],B[y]),z3,z4,z5,a,b;
if((z3=rmq(A[y],z1))!=z1)a=z1;
else if((z4=rmq(A[y],A[x]))!=z1)a=z4;
else a=rmq(A[y],B[x]);
if(rmq(a,A[y])!=a&&rmq(a,B[y])!=a||rmq(a,z2)!=z2)return 0;
if((z3=rmq(B[y],z1)!=z1))b=z1;
else if((z4=rmq(B[y],A[x]))!=z1)b=z4;
else b=rmq(B[y],B[x]);
if(rmq(b,A[y])!=b&&rmq(b,B[y])!=b||rmq(b,z2)!=z2)return 0;
LL d=getd(a,b),d1=getd(A[x],a),d2=getd(A[y],a);
bool flg=0;if(d1>getd(A[x],b))flg=1,d1=getd(A[x],b);
if(flg)return (d1+d)*V[y]>=d2*V[x]&&(d2+d)*V[x]>=d1*V[y];
return d1*V[y]<=d2*V[x]&&(d2+d)*V[x]<=(d1+d)*V[y]||d2*V[x]<=d1*V[y]&&(d1+d)*V[y]<=(d2+d)*V[x];
}
int main(){
LL _,i,j,x,y,z;
x=0;j=2;
rep(i,3,200000){
if(i>j)j<<=1,++x;
lg[i]=x;
}
for(_=read();_--;){
n=read();
memset(he,0,sizeof he);tot=1;
rep(i,2,n){
x=read();y=read();z=read();
add(x,y,z);add(y,x,z);
}
id=0;DFS(1,0);
per(i,id,1){
Min[i][0]=phi[i];
for(j=1;i+(1<<j)-1<=id;++j)
Min[i][j]=les(Min[i][j-1],Min[i+(1<<j-1)][j-1]);
}
m=read();ans=0;
rep(i,1,m){
A[i]=read();B[i]=read();V[i]=read();
per(j,i-1,1)ans+=check(i,j);
}
printf("%d\n",ans);
}
return 0;
}