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

 

你可能感兴趣的:(HDU)