CF161D 树形dp

【题意】:给出一棵树,每条边的长度为1,问树上有多少点对的距离恰好为k。

【题解】:用树的分治可解,但是写起来比较麻烦。
               设状态dp[i][j]表示以i为根的子树的节点到i的距离恰为j的个数。

               然后利用乘法原理求出答案,再把儿子的信息传给父亲。

 1 #include<cstdlib>
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<string>
 7 #include<map>
 8 #include <algorithm>
 9 #include<set>
10 #include<vector>
11 #define LL long long
12 #define inf 0x7fffffff
13 #define E 1e-9
14 #define N 50009
15 #define M 509
16 using namespace std;
17 int m,n,k;
18 LL d[N][M];
19 vector<int> g[N];
20 LL ans;
21 void dfs(int x,int f)
22 {
23     int s=g[x].size();
24     d[x][0]=1;//本身自己
25     for(int i=0; i<s; i++)
26     {
27         int u=g[x][i];
28         if(u==f)
29             continue;
30         dfs(u,x);
31         for(int j=0; j<k; j++)
32             ans+=d[u][j]*d[x][k-1-j];//相加等于k-1
33         for(int j=1; j<=k; j++)
34             d[x][j]+=d[u][j-1];
35     }
36 }
37 int main()
38 {
39 #ifndef ONLINE_JUDGE
40     freopen("ex.in","r",stdin);
41 #endif
42     scanf("%d%d",&n,&k);
43     ans=0;//全局
44     int x,y;
45     for(int i=1; i<n; ++i)
46     {
47         scanf("%d%d",&x,&y);
48         g[x].push_back(y);
49         g[y].push_back(x);
50     }
51     dfs(x,-1);
52     printf("%I64d\n",ans);
53 
54     return 0;

55 } 

posted @ 2012-11-20 21:42  baoff  阅读(281)  评论(0编辑  收藏  举报