树形DP(简单题)(Y HDU4705)

来源:互联网 发布:外国的知乎 编辑:程序博客网 时间:2024/06/05 00:29

题意:给出一个n个节点的树形图,统计{A,B,C}的数量,其中ABC分别是树上三个不同的节点,并且这三个节点不能被一条路径覆盖

分析:对于下图


进行dfs深搜统计,num[u]统计回溯到当前节点u,并以u为根节点的子树节点个数,当回溯点到<2,4>不存在,当回溯到<2,5>时可以从{4}中和{5}中分别选择一个然后在选择4到5路径之外的其他任意一点此时ans+=(num[2]-1)*num[5]*(8-num[2]-num[5])=5;当回溯到<2,6>的时候,num[2]={4,5,2};num[6]={6};然后分别从这两个集合中分别选一个元素然后再之外选择一个ans+=(num[2]-1)*num[6]*(8-num[2]-num[6])=5+2*1*4.......最后的ans=18,这种统计方法不会有重复的数据;

#pragma comment(linker, "/STACK:1024000000,1024000000")#include"stdio.h"#include"string.h"#include"stdlib.h"#include"queue"#include"algorithm"#include"string.h"#include"string"#include"math.h"#include"vector"#include"stack"#include"map"#define eps 1e-4#define inf 10000000#define M 100009#define PI acos(-1.0)using namespace std;struct node{    int u,v,next;}edge[M*2];int t,head[M],degree[M];__int64 ans,num[M],n;void init(){    t=0;    memset(head,-1,sizeof(head));}void add(int u,int v){    edge[t].u=u;    edge[t].v=v;    edge[t].next=head[u];    head[u]=t++;}void dfs(int u,int f){    num[u]=1;    for(int i=head[u];~i;i=edge[i].next)    {        int v=edge[i].v;        if(v==f)continue;        dfs(v,u);        ans+=(num[u]-1)*num[v]*(n-num[u]-num[v]);        num[u]+=num[v];    }}int main(){    int i,a,b;    while(scanf("%I64d",&n)!=-1)    {        init();        for(i=1;i<n;i++)        {            scanf("%d%d",&a,&b);            add(a,b);            add(b,a);        }        ans=0;        dfs(1,-1);        printf("%I64d\n",ans);    }}


0 0
原创粉丝点击