[树形dp] Jzoj P5248 花花的聚会

Description

 

Input

Output

 

Sample Input

7 7
3 1
2 1
7 6
6 3
5 3
4 3
7 2 3
7 1 1
2 3 5
3 6 2
4 2 4
5 3 10
6 1 20
3
5
6
7

Sample Output

10
22
5
 

Data Constraint

 

Hint

 

题解

  • 题目大意:给定一棵有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 }

 

posted @ 2018-08-07 21:08  BEYang_Z  阅读(489)  评论(0编辑  收藏  举报