[树形dp] Jzoj P5248 花花的聚会
题解
- 题目大意:给定一棵有n个节点的树,在某一些节点,可以用wi的费用向上走ki步,现在查询q个询问,询问一些节点向根节点的最小代价
- 设f[u]为u点走到根节点的最小代价
- 显然,方程就是:f[u]=min(f[u],f[v]+wi)(而且i要满足dep[u]-dep[v]<=ki)
- 然后,可以暴力的向上跳到祖先,在ki的范围内取min值
代码
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 const int inf=0x7fffffff; 5 struct edge { int k,w,to; }e[100010]; 6 int n,m,q,cnt,fa[100010],f[100010],head[100010]; 7 void insert(int v,int k,int w) { e[++cnt].k=k; e[cnt].w=w; e[cnt].to=head[v]; head[v]=cnt; } 8 int dp(int x) 9 { 10 if (x==1) return 0; 11 if (f[x]!=-1) return f[x]; 12 f[x]=inf; 13 for (int i=head[x];i;i=e[i].to) 14 { 15 int v=fa[x]; 16 for (int j=1;j<=e[i].k&&v>=1;j++) 17 { 18 f[x]=min(f[x],dp(v)+e[i].w); 19 v=fa[v]; 20 } 21 } 22 return f[x]; 23 } 24 int main() 25 { 26 scanf("%d%d",&n,&m); 27 for (int i=1;i<=n-1;i++) 28 { 29 int u,v; 30 scanf("%d%d",&u,&v); 31 fa[u]=v; 32 f[i]=head[i]=-1; 33 } 34 f[n]=head[n]=-1; 35 for (int i=1;i<=m;i++) 36 { 37 int v,k,w; 38 scanf("%d%d%d",&v,&k,&w); 39 insert(v,k,w); 40 } 41 scanf("%d",&q); 42 for (int i=1;i<=q;i++) 43 { 44 int x; 45 scanf("%d",&x); 46 printf("%d\n",dp(x)); 47 } 48 return 0; 49 }