HDU 4705 Y

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);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42671946/article/details/82912211
y