hdu 4705(树形DP)

来源:互联网 发布:mac php protobuf 编辑:程序博客网 时间:2024/06/16 04:24

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4705

思路:反面考虑,用总的方案数减去A,B,C三点在同一路径上的方案数。于是我们可以确定中间点B,在当前以B为根求得的son中任选一个,在剩下的节点n-tmp-1(tmp为已经求得的B的儿子的个数)中任选一个,产生tmp*(n-tmp-1)中组合。

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MAXN 100100 7 #pragma comment(linker, "/STACK:16777216") 8  9 struct Edge{10     int v,next;11 }edge[MAXN*4];12 13 int NE;14 long long n;15 int head[MAXN];16 17 void Insert(int u,int v)18 {19     edge[NE].v=v;20     edge[NE].next=head[u];21     head[u]=NE++;22 }23 24 25 bool mark[MAXN];26 long long sum,ans;27 28 int dfs(int u)29 {30     mark[u]=true;31     int son,tmp=0;32     for(int i=head[u];i!=-1;i=edge[i].next){33         int v=edge[i].v;34         if(mark[v])continue;35         son=dfs(v);//当前分支儿子的个数36         tmp+=son;//已经求出的儿子的个数37         ans+=(long long )(n-1-tmp)*son;38     }39     return tmp+1;40 }41 42 43 int main()44 {45     int u,v;46     while(~scanf("%I64d",&n)){47         NE=0;48         memset(head,-1,sizeof(head));49         for(int i=1;i<n;i++){50             scanf("%d%d",&u,&v);51             Insert(u,v);52             Insert(v,u);53         }54         memset(mark,false,sizeof(mark));55         ans=0;56         dfs(1);57         sum=n*(n-1)*(n-2)/6;58         printf("%I64d\n",sum-ans);59     }60     return 0;61 }
View Code

 

0 0
原创粉丝点击