【NOIP2016练习】T2 花花的聚会 (树形DP,倍增)
题意:
花花住在 H 国。H 国有 n 个城市,其中 1 号城市为其首都。城市间有 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.