【NOIP2016练习】T2 花花的聚会 (树形DP,倍增)

题意:

花花住在 H 国。H 国有 n 个城市,其中号城市为其首都。城市间有 n 1 单向道路。从任意一个城市出发,都可以沿着这些单向道路一路走到首都。事实上,从任何一个城市走到首都的路径是唯一的。

 

过路并不是免费的。想要通过某一条道路,你必须使用一次过路券。H 国一共有 m 种过路券,每张过路券以三个整数表示:v k w:你可以在城市 v 以价格 w 买到一张过路券。这张券可以使用 k 次。这意味着,拿着这张券通过了 k 条道路之后,这张券就不能再使用了。

 

请注意你同一时间最多只能拥有最多一张过路券。但你可以随时撕掉手中已有的过路券,并且在所在的城市再买一张。

 

花花家在首都。他有 q 位朋友,他希望把这些朋友们都邀请到他家做客。所以他想要知道每位朋友要花多少路费。他的朋友们都很聪明,永远都会选择一条花费最少的方式到达首都。

 

花花需要准备晚餐去了,所以他没有时间亲自计算出朋友们将要花费的路费。你可以帮帮他么?

 

4.2 输入格式

 

输入的第一行包含两个空格隔开的整数 n  m,表示 H 国的城市数量和过路券的种数。之后的 n 1 行各自包含两个数 ai  bi,代表城市 ai 到城市 bi 间有一条单向道路。

 

之后的 m 行每行包括三个整数 vi; ki  wi,表示一种过路券。下一行包含一个整数 q,表示花花朋友的数量。

 

之后的 q 行各自包含一个整数,表示花花朋友的所在城市。

 

4.3 输出格式

 

输出共 q 行,每一行代表一位朋友的路费。

对于 100% 的数据:n; m; q  105; wi    10000; 1   vi; ki    n

 

思路:

 1 var f,g:array[0..100001,0..21]of longint;
 2     head,vet,next,hq,vq,nq,lq,dp:array[1..300000]of longint;
 3     n,m,i,tot,tq,x,q,y,v,k,w:longint;
 4 
 5 procedure add(a,b:longint);
 6 begin
 7  inc(tot);
 8  next[tot]:=head[a];
 9  vet[tot]:=b;
10  head[a]:=tot;
11 end;
12 
13 procedure adq(a,b,c:longint);
14 begin
15  inc(tq);
16  nq[tq]:=hq[a];
17  vq[tq]:=b;
18  lq[tq]:=c;
19  hq[a]:=tq;
20 end;
21 
22 function min(x,y:longint):Longint;
23 begin
24  if x<y then exit(x);
25  exit(y);
26 end;
27 
28 function clac(x,y:longint):longint;
29 var i:longint;
30 begin
31  clac:=1000000000;
32  for i:=20 downto 0 do
33   if y and (1<<i)>0 then
34   begin
35    clac:=min(clac,g[x,i]);
36    x:=f[x,i];
37   end;
38 end;
39 
40 procedure dfs(u,fa:longint);
41 var e,v,i:longint;
42 begin
43  e:=hq[u];
44  while e<>0 do
45  begin
46   dp[u]:=min(dp[u],lq[e]+clac(u,vq[e]));
47   e:=nq[e];
48  end;
49 
50  e:=head[u];
51  while e<>0 do
52  begin
53   v:=vet[e];
54   if v<>fa then
55   begin
56    f[v,0]:=u;
57    g[v,0]:=dp[u];
58    for i:=1 to 20 do
59    begin
60     f[v,i]:=f[f[v,i-1],i-1];
61     g[v,i]:=min(g[v,i-1],g[f[v,i-1],i-1]);
62    end;
63    dfs(v,u);
64   end;
65   e:=next[e];
66  end;
67 end;
68 
69 begin
70  assign(input,'party.in'); reset(input);
71  assign(output,'party.out'); rewrite(output);
72  readln(n,m);
73  for i:=1 to n-1 do
74  begin
75   readln(x,y);
76   add(x,y);
77   add(y,x);
78  end;
79  for i:=1 to m do
80  begin
81   readln(v,k,w);
82   adq(v,k,w);
83  end;
84  for i:=1 to n do dp[i]:=1000000000;
85  dp[1]:=0;
86  dfs(1,-1);
87  readln(q);
88  for i:=1 to q do
89  begin
90   readln(x);
91   writeln(dp[x]);
92  end;
93 
94 
95  close(input);
96  close(output);
97 end.

 

posted on 2016-11-02 15:48  myx12345  阅读(488)  评论(0编辑  收藏  举报

导航