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 }