思路:反面考虑,用总的方案数减去A,B,C三点在同一路径上的方案数。于是我们可以确定中间点B,在当前以B为根求得的son中任选一个,在剩下的节点n-tmp-1(tmp为已经求得的B的儿子的个数)中任选一个,产生tmp*(n-tmp-1)中组合。
//#pragma comment(linker, "/STACK:102400000,102400000")
#pragma comment(linker, "/STACK:16777216")
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
using namespace std;
typedef long long LL;
const int INF =1000000000;
const int M = 10000010;
const int MAXN = 100100;
struct Edge
{
int v,next;
} edge[MAXN*4];
int NE;
long long n;
int head[MAXN];
void Insert(int u,int v)
{
edge[NE].v=v;
edge[NE].next=head[u];
head[u]=NE++;
}
bool mark[MAXN];
LL sum,ans;
int dfs(int u)
{
mark[u]=true;
int son,tmp=0;
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].v;
if(mark[v])
continue;
son=dfs(v);//当前分支儿子的个数
tmp+=son;//已经求出的儿子的个数
ans+=(LL)(n-1-tmp)*son;
}
return tmp+1;
}
int main()
{
int u,v;
while(~scanf("%I64d",&n))
{
NE=0;
memset(head,-1,sizeof(head));
for(int i=1; i<n; i++)
{
scanf("%d%d",&u,&v);
Insert(u,v);
Insert(v,u);
}
memset(mark,false,sizeof(mark));
ans=0;
dfs(1);
sum=n*(n-1)*(n-2)/6;
printf("%I64d\n",sum-ans);
}
return 0;
}