传送门
www.lydsy.com/JudgeOnline/problem.php?id=3522
题目大意
给定一棵树,找到三个不同的点,使得三个点两两间距离相等,询问方案数
题解
三个点肯定在三个不同的子树里,不可能是在同一条链上
枚举根,处理出子树中的深度为i的点数
当给定
a1a2+a1a3+a1a4+a1a5+a2a3+a2a4+a2a5+a3a4+a3a5+a4a5=a5(a1+a2+a3+a4)+a4(a1+a2+a3)+a3(a1+a2)+a2(a1)
就可以O(1)递推了
再说这题的任取三个
a1a2a3+a1a2a4+a1a2a5+a1a3a4+a1a3a5+a1a4a5+a2a3a4+a2a3a5+a2a4a5+a3a4a5=a3(a1a2)+a4(a1a2+a1a3+a2a3)+a5(a1a2+a1a3+a1a4+a2a3+a2a4+a3a4)
括号里的就是任取两个的形式了
const
maxn=5050;
var
w:array[0..3*maxn,1..2]of longint;
dep,num:array[0..maxn]of longint;
s1,s2:array[0..maxn]of int64;
i,j,k:longint;
n,m,len,a,b,tt,temp:longint;
ans:int64;
function max(a,b:longint):Longint;
begin if a>b then exit(a) else exit(b); end;
procedure init(a,b:longint);
begin
w[len,1]:=b;
if w[a,2]=0 then w[a,2]:=len else w[w[a,1],2]:=len;
w[a,1]:=len; inc(len);
end;
procedure dfs(a,fa:longint);
var tt:longint;
begin
inc(num[dep[a]]); temp:=max(temp,dep[a]); tt:=w[a,2];
while tt<>0 do
begin
if (w[tt,1]<>fa) then
begin
dep[w[tt,1]]:=dep[a]+1;
dfs(w[tt,1],a);
end;
tt:=w[tt,2];
end;
end;
begin
readln(n); len:=n+1; ans:=0;
for i:=1 to n-1 do
begin readln(a,b); init(a,b); init(b,a); end;
for i:=1 to n do
begin
tt:=w[i,2];
fillchar(s1,sizeof(s1),0);
fillchar(s2,sizeof(s2),0);
while tt<>0 do
begin
dep[w[tt,1]]:=1; dfs(w[tt,1],i);
for j:=1 to temp do
begin
inc(ans,s2[j]*num[j]);
inc(s2[j],s1[j]*num[j]);
inc(s1[j],num[j]);
end;
for j:=1 to temp do
num[j]:=0;
tt:=w[tt,2];
end;
end;
writeln(ans);
end.