HLG 1359 Leyni的国家II【树形DP】
题意: 有 n 个国家,n-1 条道路,形成的树形地图,问图中有多少对城市距离为 K ...
分析: 可以用 f[i][j] 表示以 I 为根的子树中有多少定点距离 i 为 j 。因为
f[i][j]=f[son1][j-1]+f[son2][j-1]....f[son(n)][j-1]
即每个 I 号根都可以由和它直接相连的孩子得到,这个过程可以利用树形搜索的方式来完成,
至于最终答案,只要逐个累加即可,例如 f[i][j] i 号节点得到的数目为 f[i][k]+f[son1][j]*f[son2][k-2-j] (son为i 的直接孩子)
View Code
#include<stdio.h> #include<string.h> int res; int f[50002][503]; struct node { int to,next; }q[100000]; int tot; int head[50005]; void add(int s,int u) { q[tot].to=u; q[tot].next=head[s]; head[s]=tot++; } int v[50005]; int k; void dfs(int r) { int flag=1,i,j,z,top=0,son; int a[10000]; v[r]=1; f[r][0]=1; v[r]=1; for(i=head[r];i;i=q[i].next) { son=q[i].to; if(!v[son]) { flag=0; dfs(son); a[top++]=son; for(j=1;j<=k;j++) f[r][j]+=f[son][j-1]; } } for(i=0;i<top;i++) { res+=f[a[i]][k-1]; for(j=i+1;j<top;j++) for(z=0;z<=k-2;z++) res+=f[a[i]][z]*f[a[j]][k-z-2]; } } int main() { //freopen("D:ce.txt","r",stdin); int t,i,n,a,b; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&k); memset(head,0,sizeof(head)); memset(f,0,sizeof(f)); memset(v,0,sizeof(v)); tot=1; for(i=0;i<n-1;i++) { scanf("%d%d",&a,&b); add(a,b); add(b,a); } res=0; dfs(1); printf("%d\n",res); } return 0; }
View Code
#include <stdio.h> #include <iostream> #include <vector> using namespace std; #define maxn 50500 #define maxk 505 using namespace std; int n,k; vector<int> g[maxn]; int dp[maxn][maxk]={0}; long long res = 0; void dfs(int v,int p) { dp[v][0] = 1; int i,j; for (i=0; i<g[v].size(); i++) { int u = g[v][i]; if (u==p) continue; dfs(u,v); for (j=0; j<k; j++) res += (long long)dp[u][j]*dp[v][k-j-1]; for (j=0; j<k; j++) dp[v][j+1] += dp[u][j]; } } int main() { scanf("%d %d",&n,&k); for(int i=0;i<n-1;i++) { int v,u; scanf("%d %d",&v,&u); g[v].push_back(u); g[u].push_back(v); } dfs(1,0); printf("%I64d\n",res); return 0; }