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