Y(类树形DP)

Posted 1013star

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Y(类树形DP)相关的知识,希望对你有一定的参考价值。

Y

 HDU - 4705 

技术分享图片

题意:给你一棵树,n个节点n-1条边(双向),树上任意三个点不在一条路径上,统计这样的三点集合有多少种。

思路:

  n个节点中任选3个点的方案数为n*(n-1)*(n-2)/6,从中减去三个点在同一条路径上的种类数即为答案。如何找在同一条路径上的方案数呢,就是以固定某一个点,看看他的一个儿子有几个儿子,儿子的儿子个数加上儿子本身,从这些点中选一个,再从剩余的点中选一个,即可以构成三个点在同一条直线上。所有对于固定的这个点x,方案数为sum[son]*(n-sum[x])

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
vector<int>v[maxn];
int vis[maxn];
int a,b;
ll ans,n,t,son[maxn];
void dfs(int x)
{
    vis[x]=1;
    son[x]=1;
    for(int i=0;i<v[x].size();i++)
    {
        int to=v[x][i];
        if(vis[to])
            continue;
        dfs(to);
        son[x]+=son[to];
        ans+=(n-son[x])*son[to]; 
    }
}
int main()
{
    while(~scanf("%lld",&n))
    {
        ans=0;
        memset(son,0,sizeof(son));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=n;i++)
            v[i].clear();
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            v[a].push_back(b); 
            v[b].push_back(a);
        }
        dfs(1);
        t=(n-1)*n*(n-2)/6;
        printf("%lld
",t-ans);
    }
}

这个题的思路和hdu2376有些像,果然要学着举一反三啊啊啊啊啊啊~~~

以上是关于Y(类树形DP)的主要内容,如果未能解决你的问题,请参考以下文章

动态规划_计数类dp_数位统计dp_状态压缩dp_树形dp_记忆化搜索

HDOJ 4705 Y 树形DP

HDU - 4809 树形dp

树形dp——游族杯 D

洛谷4438 [Hnoi2018]道路 树形dp

hdu 4705 Y (树形dp)