http://acm.hdu.edu.cn/showproblem.php?pid=4705
题意:求树中不在一条线上的3个点的种数。
按照题意直接去求显然不好做,可以用总数减去树中在一条线上的3个点的种数,剩下的就是题中所求。
注意,只要三个点可以连起来就算作一种情况,即中间可以有其他点,边是双向的。
对于其中一种情况 A--B--C 我们选取中间点B点为参考点,C是B的儿子节点,A是除了B和B的儿子节点以外的点。
那么对于这种情况,ans=n-son[B])*son[B] 所以我们只需要dfs遍历即可求出树中在一条线上的3个点的种数,而总数直接用组合数求即可。
#include"bits/stdc++.h"
using namespace std;
vector<long long>vt[100004];
long long son[100004];
bool vis[100004];
long long ans;
long long n;
void dfs(long long u)
{
vis[u]=1;
for(int i=0;i<vt[u].size();i++)
{
long long t=vt[u][i];
if(!vis[t])
{
dfs(t);
son[u]+=son[t];
ans+=(son[t])*(n-son[u]);
}
}
}
int main()
{
while(~scanf("%lld",&n))
{
//memset(son,1,sizeof(son));
memset(vis,0,sizeof(vis));
ans=0;
for(int i=0;i<=n;i++)
{
vt[i].clear();
son[i]=1;
}
long long u,v;
for(int i=0;i<n-1;i++)
{
scanf("%lld%lld",&u,&v);
vt[u].push_back(v);
vt[v].push_back(u);
}
dfs(1);
printf("%lld\n",n*(n-1)*(n-2)/6-ans);
}
}