题目
Description
给出一棵N 个点的树,点的编号是1, 2,。。。,N。
对于3 个点{a,b,c},如果不存在一条简单路径同时经过a,b,c,那么{a,b,c}是一个分叉。
统计不同分叉的数量。
树 无环,连通的无向图
简单路径 不重复经过同一个点的路径
Input
第1 行,1 个整数N。接下来(N -1) 行,每行2 个整数Ai,Bi,表示点Ai 和点Bi 间有一条边。
Output
1 个整数,表示所求的值。
Sample Input
5
1 2
1 3
1 4
1 5
Sample Output
4
Data Constraint
• 对于30% 的数据,N <= 100;
• 对于50% 的数据,N <= 1000;
• 对于100% 的数据,1 <= N <= 10^5。
题解
我们可以反着做,也就是找出合法的{x,y,z}三元组
那么我们可以枚举y,而x和z分别在以y为根形成的树的两颗子树里面,计算每一个y对应的组数,这样就不会有重复的情况了
贴代码
var
a,b:array[0..200005,1..2]of longint;
father,son:array[0..100005]of longint;
size:array[0..100005]of int64;
bz:array[0..100005]of boolean;
i,j,k,l,m,n,x,y,z:longint;
ans,nn,p:int64;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=a[(i+j) div 2,1];
repeat
while a[i,1]<mid do inc(i);
while a[j,1]>mid do dec(j);
if i<=j then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure star;
begin
b[a[1,1],1]:=1;
for i:=2 to k do
if a[i,1]<>a[i-1,1] then
begin
b[a[i-1,1],2]:=i-1;
b[a[i,1],1]:=i;
end;
b[a[k,1],2]:=k;
end;
procedure dfs(x:longint);
var
i:longint;
begin
bz[x]:=true;
for i:=b[x,1] to b[x,2] do
if (i<>0) and (bz[a[i,2]]=false) then
begin
father[a[i,2]]:=x;
inc(son[x]);
dfs(a[i,2]);
size[x]:=size[x]+size[a[i,2]];
end;
inc(size[x]);
end;
begin
//assign(input,'t3.in'); reset(input);
assign(input,'fork.in'); reset(input);
assign(output,'fork.out'); rewrite(output);
readln(n);
for i:=1 to n-1 do
begin
readln(a[i,1],a[i,2]);
a[i+n-1,1]:=a[i,2];
a[i+n-1,2]:=a[i,1];
end;
k:=2*n-2;
qsort(1,k);
star;
dfs(1);
nn:=n;
ans:=trunc(nn*(nn-1)/6*(nn-2));
for i:=1 to n do
if son[i]>0 then
begin
p:=0;
for j:=b[i,1] to b[i,2] do
if a[j,2]<>father[i] then
begin
ans:=ans-size[a[j,2]]*(nn-size[a[j,2]]-1-p);
p:=p+size[a[j,2]];
end;
end;
writeln(ans);
close(input); close(output);
end.