1. 程式人生 > >VK Cup 2012 Round 1 D. Distance in Tree (樹形dp)

VK Cup 2012 Round 1 D. Distance in Tree (樹形dp)

tree 樹形dp ios stream int print efi problems str

題目: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]; }

VK Cup 2012 Round 1 D. Distance in Tree (樹形dp)