在读完题以后,一开始不会,我就想那么简单,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;
}

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

被折叠的 条评论
为什么被折叠?



