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

题目: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 2016 - Round 3] - D Bearish Fanpages


下一篇:Mail.Ru Cup 2018 Round 3