HDU 4705 树形DP

68 篇文章 0 订阅

2013 Multi-University Training Contest 10

有一颗树, 选出3个点。 不在同一条路径上的集合数。

树形DP做遍DFS即可

分别考虑 

A,B分别位于cur的不同儿子,C在cur的祖先

A,B,C分别位于cur的不同儿子


#include "stdio.h"
#include "string.h"
#include "vector"
#pragma comment(linker, "/STACK:16777216")
using namespace std;

vector<int>map[100010];
__int64 ans;
__int64 dp[100010],cnt[100010];
int n;
__int64 cal(int cur,int pre)
{
    int i;
    for (i=0;i<map[cur].size();i++)
        if (map[cur][i]!=pre)
        cnt[cur]+=cal(map[cur][i],cur);
    cnt[cur]++;
    return cnt[cur];

}

__int64 dfs(int cur,int pre)
{
    int i;
    for (i=0;i<map[cur].size();i++)
        if (map[cur][i]!=pre)
    {
        ans+=dp[cur]*cnt[map[cur][i]]*(n-cnt[cur]); // A,B分别位于cur的不同儿子,C在cur的祖先
        ans+=dp[cur]*cnt[map[cur][i]]*(cnt[cur]-1-dp[cur]-cnt[map[cur][i]]); //A,B,C分别位于cur的不同儿子
        dp[cur]+=dfs(map[cur][i],cur);
    }
    dp[cur]++;
    return dp[cur];


}
int main()
{
    int i,a,b;
    while (scanf("%d",&n)!=EOF)
    {
        for (i=1;i<=n;i++)
            map[i].clear();
        for (i=2;i<=n;i++)
        {
            scanf("%d%d",&a,&b);
            map[a].push_back(b);
            map[b].push_back(a);
        }
        ans=0;
        memset(cnt,0,sizeof(cnt));
        memset(dp,0,sizeof(dp));
        cal(1,-1);
        dfs(1,-1);
        printf("%I64d\n",ans);
    }
    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值