描述
有 n + 1 n+1 n+1棵树 T 0 , T 1 , … , T n T_0,T_1,\dots,T_n T0,T1,…,Tn。 T 0 T_0 T0只有 0 0 0号节点,对于 T i ( i ∈ [ 1.. m ] ) T_i(i\in [1..m]) Ti(i∈[1..m]),给出 a i , 1 , a i , 2 , b i , 1 , b i , 2 , l e n i a_{i,1},a_{i,2},b_{i,1},b_{i,2},len_i ai,1,ai,2,bi,1,bi,2,leni,表示这棵树是由 T a i , 1 T_{a_{i,1}} Tai,1与 T b i , 1 T_{b_{i,1}} Tbi,1构成,且 T a i , 1 T_{a_{i,1}} Tai,1的第 a i , 2 a_{i,2} ai,2个点与 T b i , 1 T_{b_{i,1}} Tbi,1的第 b i , 2 b_{i,2} bi,2个点连接一条长度为 l e n i len_i leni的边。在 T i T_i Ti中,保持 T a i , 1 T_{a_{i,1}} Tai,1中的所有节点编号不变,如果 T a i , 1 T_{a_{i,1}} Tai,1中有 s s s个节点,他会把 T b i , 1 T_{b_{i,1}} Tbi,1中的所有节点的编号加上 s s s。
对于 T i ( i ∈ [ 1.. n ] ) T_i(i\in [1..n]) Ti(i∈[1..n]),求位于 T i T_i Ti中互不相同的两个点的距离之和。
n ≤ 1 0 2 n\leq 10^2 n≤102, 0 ≤ a i , b i < i 0 \leq ai, bi < i 0≤ai,bi<i, 0 ≤ l i ≤ 1 0 9 0\leq li\leq 10^9 0≤li≤109
分析
令 A n s i Ans_i Ansi表示 T i T_i Ti的答案, s i z e i size_i sizei表示 ∣ T i ∣ \left | T_i \right | ∣Ti∣, t o p v , x top_{v,x} topv,x表示 T v T_v Tv中所有节点与 x x x的距离之和。则
A n s i = A n s a i , 1 + A n s b i , 1 + t o p a i , 1 , a i , 2 × s i z e b i , 1 + t o p b i , 1 , b i , 2 × s i z e a i , 1 + l e n i × s i z e a i , 1 × s i z e b i , 1 Ans_i=Ans_{a_{i,1}}+Ans_{b_{i,1}}+top_{a_{i,1},a_{i,2}}\times size_{b_{i,1}}+top_{b_{i,1},b_{i,2}}\times size_{a_{i,1}}+len_i\times size_{a_{i,1}}\times size_{b_{i,1}} Ansi=Ansai,1+Ansbi,1+topai,1,ai,2×sizebi,1+topbi,1,bi,2×sizeai,1+leni×sizeai,1×sizebi,1
定义solve(v,x)
求解
t
o
p
v
,
x
top_{v,x}
topv,x,设
D
i
s
v
,
x
,
y
Dis_{v,x,y}
Disv,x,y表示在
T
v
T_v
Tv中
x
→
y
x\rightarrow y
x→y的距离。
考虑将 T v T_v Tv分成 T a v , 1 , T b v , 1 T_{a_{v,1}},T_{b_{v,1}} Tav,1,Tbv,1
-
v
=
0
v=0
v=0。
solve(v,x)
返回 0 0 0 -
x
<
s
i
z
e
a
v
,
1
x<size_{a_{v,1}}
x<sizeav,1。说明
x
x
x在
T
a
v
,
1
T_{a_{v,1}}
Tav,1中,
solve(v,x)
返回 t o p a v , 1 , x + t o p b v , 1 , b v , 2 + ( l e n v + D i s a v , 1 , a v , 2 , x ) × s i z e b v , 1 top_{a_{v,1},x}+top_{b_{v,1},b_{v,2}}+(len_v+Dis_{a_{v,1},a_{v,2},x})\times size_{b_{v,1}} topav,1,x+topbv,1,bv,2+(lenv+Disav,1,av,2,x)×sizebv,1 - x ≥ s i z e a v , 1 x\geq size_{a_{v,1}} x≥sizeav,1。同理得到一个类似的返回值。
于是调用solve(v,x)
即可得到
t
o
p
v
,
x
top_{v,x}
topv,x。问题转化为求解
D
i
s
v
,
x
,
y
Dis_{v,x,y}
Disv,x,y
- x = y x=y x=y或 v = 0 v=0 v=0,返回 0 0 0
- x , y x,y x,y在 T v T_v Tv中同一棵树中,则继续递归下去。
- 否则,令 x < y x<y x<y,则 D i s v , x , y ← D i s a v , 1 , a v . 2 , x + D i s b v , 1 , b v , 2 , y + l e n v Dis_{v,x,y}\leftarrow Dis_{a_{v,1},a_{v.2},x}+Dis_{b_{v,1},b_{v,2},y}+len_v Disv,x,y←Disav,1,av.2,x+Disbv,1,bv,2,y+lenv
用 H a s h Hash Hash记忆化一下即可。
时间复杂度 O ( n 3 ) O(n^3) O(n3)
代码
const
mo=1000000007; mo1=449363; mo2=447001;
var
t,n,i:longint;
a,b:array[0..60,0..2] of int64;
hash:array[0..500000,1..3] of int64;
hash2:array[0..500000,1..4] of int64;
ans,len,size,size1:array[0..60] of int64;
procedure swap(var x,y:int64);
var
z:int64;
begin
z:=x; x:=y; y:=z;
end;
procedure put(x:longint;y,z:int64);
var
k:longint;
begin
k:=(sqr(x)+sqr(y mod mo1)) mod mo1;
while hash[k,3]<>0 do inc(k);
hash[k,1]:=x; hash[k,2]:=y; hash[k,3]:=z;
end;
function find(x:longint;y:int64):longint;
var
k:longint;
begin
k:=(sqr(x)+sqr(y mod mo1)) mod mo1;
while hash[k,3]<>0 do
begin
if (hash[k,1]=x) and (hash[k,2]=y) then exit(hash[k,3]);
inc(k);
end;
exit(0);
end;
procedure put2(x:longint;y,z,o:int64);
var
k:longint;
begin
k:=(sqr(x)+sqr(y mod mo2)+sqr(z mod mo2)) mod mo2;
while hash2[k,4]<>0 do inc(k);
hash2[k,1]:=x; hash2[k,2]:=y; hash2[k,3]:=z; hash2[k,4]:=o;
end;
function find2(x:longint;y,z:int64):longint;
var
k:longint;
begin
k:=(sqr(x)+sqr(y mod mo2)+sqr(z mod mo2)) mod mo2;
while hash2[k,3]<>0 do
begin
if (hash2[k,1]=x) and (hash2[k,2]=y) and (hash2[k,3]=z) then exit(hash2[k,4]);
inc(k);
end;
exit(0);
end;
function dis(v:longint;x,y:int64):int64;
var
now:int64;
begin
if (v=0) or (x=y) then exit(0);
now:=find2(v,x,y); if now>0 then exit(now);
if (x<size[a[v,1]]) and (y<size[a[v,1]]) then
now:=dis(a[v,1],x,y)
else
if (x>=size[a[v,1]]) and (y>=size[a[v,1]]) then
now:=dis(b[v,1],x-size[a[v,1]],y-size[a[v,1]])
else
begin
if x>y then swap(x,y);
now:=(dis(a[v,1],a[v,2],x)+dis(b[v,1],b[v,2],y-size[a[v,1]])+len[v]) mod mo;
end;
put2(v,x,y,now); exit(now);
end;
function solve(v:longint;x:int64):int64;
var
now:int64;
begin
if v=0 then exit(0);
now:=find(v,x); if now>0 then exit(now);
if x<size[a[v,1]] then
now:=solve(a[v,1],x)+solve(b[v,1],b[v,2])+(len[v]+dis(a[v,1],a[v,2],x)) mod mo*size1[b[v,1]] mod mo
else
now:=solve(b[v,1],x-size[a[v,1]])+solve(a[v,1],a[v,2])+(len[v]+dis(b[v,1],b[v,2],x-size[a[v,1]])) mod mo*size1[a[v,1]] mod mo;
now:=now mod mo; put(v,x,now); exit(now);
end;
begin
readln(t);
while t>0 do
begin
readln(n); dec(t);
size[0]:=1; size1[0]:=1; fillchar(hash,sizeof(hash),0); fillchar(hash2,sizeof(hash2),0);
for i:=1 to n do
begin
readln(a[i,1],b[i,1],a[i,2],b[i,2],len[i]); len[i]:=len[i] mod mo; size[i]:=size[a[i,1]]+size[b[i,1]]; size1[i]:=size[i] mod mo;
end;
ans[0]:=0;
for i:=1 to n do
begin
ans[i]:=ans[a[i,1]]+ans[b[i,1]];
ans[i]:=ans[i]+solve(a[i,1],a[i,2])*size1[b[i,1]] mod mo;
ans[i]:=ans[i]+solve(b[i,1],b[i,2])*size1[a[i,1]] mod mo;
ans[i]:=ans[i]+len[i]*size1[a[i,1]] mod mo*size1[b[i,1]] mod mo;
ans[i]:=ans[i] mod mo;
writeln(ans[i]);
end;
end;
end.