题目:http://codeforces.com/problemset/problem/161/D
题意:给你一棵树,问你两点之间的距离正好等于k的有多少个
思路:这个题目的内存限制首先大一倍,他有5*1e5个点,k的范围是<=500,首先暴力n^2肯定不行,这个题其实很容易看出是树形dp
首先k的范围只有500,我们可以开一个dp[1e5][500]的dp数组,代表以这个点为上端点的所有情况,然后最后递归到1点处,dp[1][k]就是答案
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<string> #include<vector> #define maxn 50005 #define mod 1000000007 using namespace std; typedef long long ll; vector<int> mp[maxn]; ll n,k,num; ll q[maxn][505]; void dfs(int x,int f) { for(int i=0;i<mp[x].size();i++){ int u=mp[x][i]; if(u==f) continue; dfs(u,x); q[u][0]=1;//每到一个新点,他的孩子到他的距离都是1 for(int j=k-1;j>=0;j--){ if(q[u][j]) { q[u][j+1]=q[u][j+1]+q[u][j]; q[u][j]=0; q[x][k]+=q[u][j+1]*q[x][k-j-1];//如果当前点不是上端点,只是两个孩子之间要过度的点 } } for(int j=1;j<=k;j++){ q[x][j]=q[x][j]+q[u][j]; } } /*printf("%d:",x); for(int i=0;i<=k;i++) { printf(" %d",q[x][i]); } printf("\n");*/ } int main() { cin>>n>>k; int x,y; for(int i=0;i<n-1;i++){ cin>>x>>y; mp[x].push_back(y); mp[y].push_back(x); } dfs(1,-1); /*for(int i=1;i<=n;i++) { printf("i:%d",i); for(int j=0;j<=k;j++) { printf(" %d",q[i][j]); } printf("\n"); }*/ cout<<q[1][k]; }