您的位置:首页 > 其它

[BZOJ3522] [Poi2014]Hotel

2016-03-04 08:33 375 查看

传送门

www.lydsy.com/JudgeOnline/problem.php?id=3522

题目大意

给定一棵树,找到三个不同的点,使得三个点两两间距离相等,询问方案数

题解

三个点肯定在三个不同的子树里,不可能是在同一条链上

枚举根,处理出子树中的深度为ii的点数

当给定{a1,a2,⋯,an}\{a_1,a_2,\cdots,a_n\},我们任取两个相乘求和我们是这么求的(以n=5n=5为例)

a1a2+a1a3+a1a4+a1a5+a2a3+a2a4+a2a5+a3a4+a3a5+a4a5=a5(a1+a2+a3+a4)+a4(a1+a2+a3)+a3(a1+a2)+a2(a1)a_1a_2+a_1a_3+a_1a_4+a_1a_5+a_2a_3+a_2a_4+a_2a_5+a_3a_4+a_3a_5+a_4a_5\\=a_5(a_1+a_2+a_3+a_4)+a_4(a_1+a_2+a_3)+a_3(a_1+a_2)+a_2(a_1)

就可以O(1)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)a_1a_2a_3+a_1a_2a_4+a_1a_2a_5+a_1a_3a_4+a_1a_3a_5+a_1a_4a_5+a_2a_3a_4+a_2a_3a_5+a_2a_4a_5+a_3a_4a_5\\=a_3(a_1a_2)+a_4(a_1a_2+a_1a_3+a_2a_3)+a_5(a_1a_2+a_1a_3+a_1a_4+a_2a_3+a_2a_4+a_3a_4)

括号里的就是任取两个的形式了

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: