Codeforces161D【树形DP】

本文介绍了一种使用树形动态规划的方法来解决寻找一棵树中距离为K的所有点对的问题。通过递归地遍历树并利用子树的信息,有效地计算出了所有符合条件的点对数量。

在读完题以后,一开始不会,我就想那么简单,tm我一定能过…
然后终于屯了几天后拿到加强版的POJ1741,就来再看看///就过了,嘿嘿。


题意:

求一棵树中距离为K的点对有多少个。

思路:

dp[node][j]代表 以节点为node为根的树,从node出发,存在距离长度为 k 的节点数量。
先取答案,再更新
ans += dp[node][k-p] + dp[node_son][p-1];
dp[node][p] += dp[node_son][p-1];
打完发现把以自己为根,从根出发的长度为k的那些dp值加上案例跑不出来,
然后删掉突然就过了!!万脸懵逼。。。
然后仔细一想。。挖草,我是sabi…处理了呀不就是dp[father][0]*dp[son][k-1]这种情况…

Code:

//#include <bits/stdc++.h>
#include<iostream>
#include<vector>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
//#pragma comment(linker, "/STACK:102400000,102400000")
const int N=5e4+10;
struct Edge
{
    int v;
    int next;
} edge[N<<1];

int head[N],tol;
int n,k;
void init(){
    tol=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v){
    edge[tol].v=v;
    edge[tol].next=head[u];
    head[u]=tol++;
}
bool vis[N];
LL dp[N][550];
LL ans;
void DFS(int u){
    int v;
    dp[u][0]=1;
    for(int i=head[u];~i;i=edge[i].next){
        v = edge[i].v;
        if(vis[v]) continue;
        vis[v]=true;
        DFS(v);
        for(int p=1;p<=k;p++)
            ans = ans + dp[v][p-1]*dp[u][k-p];
        for(int p=0;p<k;p++)
            dp[u][p+1] += dp[v][p];
    }
}

void input(){
    int u,v;
    scanf("%d%d",&n,&k);
    init();
    for(int i=1; i<n; i++){
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
}

void solve(){
    memset(vis,false,sizeof(vis));
    memset(dp,0,sizeof(dp));
    ans = 0;
    vis[1]=true;
    DFS(1);
    printf("%lld\n",ans);
}

int main(){
    input();
    solve();
    return 0;
}
### 关于Codeforces Educational Round 172 Problem D 的解决方案 对于Codeforces Educational Round 172中的D题,虽然未直接提供该题目具体描述以及官方解答[^2],可以基于过往相似难度和类型的题目给出一般性的解决思路。 #### 题目分析 通常情况下,D级别的题目会涉及到较为复杂的算法设计或是数据结构的应用。这类问题往往需要参赛者具备良好的编程基础、逻辑思维能力以及对特定算法的理解掌握程度。针对不同性质的问题(如图论、动态规划、字符串处理等),采取相应的策略来构建模型并求解是最常见的方法之一。 #### 解决方案框架 假设此题属于某种典型问题类别,则可以根据其特点制定如下通用框架: - **输入解析**:仔细阅读题目说明,明确给定条件与目标函数之间的关系。 - **核心概念理解**:深入剖析题目背后所隐藏的关键知识点或技巧点,这可能涉及但不限于贪心算法、二分查找、树形DP等方面的知识。 - **边界情况考虑**:考虑到极端测试用例的存在,在编写程序时要特别注意各种特殊情况下的行为表现,确保代码鲁棒性强。 - **优化空间复杂度/时间效率**:当面对大数据集时,应尽可能寻找更高效的实现方式减少不必要的计算开销;比如利用哈希表加速查询速度,通过位运算代替常规算术操作提高性能等等。 ```cpp // 假设这是一个简化版的伪代码示例 #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; // 输入参数 vector<int> data(n); for(auto& d : data){ cin>>d; } // 主体逻辑部分省略... cout << "Result"; return 0; } ``` 由于缺乏具体的题目细节,上述内容仅作为参考模板展示如何着手准备类似的竞赛挑战。为了获得更加精准的帮助建议查阅官方题解文档或者参与社区论坛交流获取更多信息资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值