hdu 4705(树形DP)

题目链接: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

 

posted @ 2013-08-23 10:15  ihge2k  阅读(722)  评论(0编辑  收藏  举报