题目
给出一棵N 个点的树,点的编号是1, 2,。。。,N。
对于3 个点{a,b,c},如果不存在一条简单路径同时经过a,b,c,那么{a,b,c}是一个分叉。
统计不同分叉的数量。
分析
比赛时爆int.
开了long long就对了
我们可以很方便的找到有一条简单路径经过{x,y,z}三元组的个数
然后拿所有的三元组个数去减就好了.
code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#define maxn 200005
#define maxm 300005
#define INF 0x7fffffff;
using namespace std;
struct arr{
int x,y;
int next;
}edge[maxm];
int ls[maxn];
int edge_m;
long long son[maxn];
long long f[maxn];
long long n;
void add(int x,int y)
{
edge[++edge_m]=(arr){x,y,ls[x]},ls[x]=edge_m;
edge[++edge_m]=(arr){y,x,ls[y]},ls[y]=edge_m;
}
int dfs(int x,int r)
{
son[x]=1;
for (int i=ls[x];i;i=edge[i].next)
{
if (edge[i].y==r) continue;
dfs(edge[i].y,x);
son[x]+=son[edge[i].y];
}
int num=1;
for (int i=ls[x];i;i=edge[i].next)
{
if (edge[i].y==r) continue;
num+=son[edge[i].y];
f[x]+=son[edge[i].y]*(n-num);
}
}
int main()
{
freopen("fork.in","r",stdin);
freopen("fork.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
dfs(1,0);
long long ans=(long long)(n*(n-1)*(n-2)/6);
for (int i=1;i<=n;i++)
{
ans-=f[i];
}
cout<<ans;
}