#pragma comment(linker, "/STACK:16777216")
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL __int64
#define maxn 100011
const int mod=1e9+7;
vector<int>e[maxn];
int c[maxn],d[maxn];
int dfs(int pre,int u)//以1为根结点
{
c[u]=1;//记录点的子树结点数和+1
d[u]=pre;//记录父节点
int i,v;
if(e[u].size()==1&&e[u][0]==pre)
return c[u];
for(i=0;i<e[u].size();i++)
{
v=e[u][i];
if(v==pre)continue;
c[u]+=dfs(u,v);
}
return c[u];
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int i,j,k,a,b;
for(i=1;i<=n;i++)
e[i].clear();
for(i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
e[a].push_back(b);
e[b].push_back(a);
}
dfs(-1,1);
/*for(i=1;i<=n;i++)
cout<<c[i]<<" ";
cout<<endl;*/
int v,u;
LL ans=0,s;
for(i=1;i<=n;i++)
{
s=0;
if(e[i].size()==1)continue;
for(j=0;j<e[i].size();j++)
{
v=e[i][j];
if(v==d[i])a=n-c[i];
else a=c[v];
b=n-a-1; //a为左符合点数,b为右符合点数
s+=(LL)a*b;
}
ans+=s/2;
}
//cout<<ans<<endl;
ans=(LL)n*(n-1)*(n-2)/6-ans;
printf("%I64d\n",ans);
}
return 0;
}
/*
样例:
Input:
3
1 2
2 3
6
1 2
2 4
2 5
1 3
3 6
Output:
0
3
方法:找到符合要求的三个点的方案数ans,答案就是C(n,3)-ans;
枚举所有结点,以这个结点为中符合点的所有方案数和就是ans
对于一个结点,在一棵子树上找一个点做左符合点,则其余子树上的点都右符合点。
举例来说,一个点有三个子树,子树结点数分别为1,2,3,则符合要求的组合有(1*5+2*4+3*3)/2(会重复一次)
*/
hdu 4705 Y/杭电2013年多校第十场1010 组合
最新推荐文章于 2024-07-20 00:21:04 发布