LA 4015 Cave
Posted ympc2005
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LA 4015 Cave相关的知识,希望对你有一定的参考价值。
树上dp
入度为零的点即没有父亲的点就是根节点
由于距离很大,不能加入到状态里,则考虑如何求出访问了 i (1 <= i <= n) 个点最小的距离
对与树的根节点而言,从它开始游历它的子树,要么在子树内结束,要么返回根节点
那么:
记 f[u][j] 表示从 u 出发访问其子树,访问了 j 个点,并且回到 u 的最小花费
记 g[u][j] 表示从 u 出发访问其子树,访问了 j 个点,最后停留在其子树内中的最小花费
讨论 u 的最终是否停留在子节点 v 的子树中,得到状态转移方程:
g[u][j] = min(g[u][j], min(f[u][j - k] + e[i].d + g[v][k], g[u][j - k] + 2*e[i].d + f[v][k]))
f[u][j] = min(f[u][j], f[v][k] + 2*e[i].d + f[u][j - k])
对于每一个x答案就是max(i) g[s][i] <= x // s == root
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int N = 505; 5 typedef long long LL; 6 7 int n, q, cnt, first[N], s, tot, siz[N]; 8 LL f[N][N], g[N][N], x; 9 bool vis[N]; 10 struct Edge { 11 int to, next; 12 LL d; 13 } e[N]; 14 15 void dfs(int u) { 16 f[u][1] = g[u][1] = 0; 17 siz[u] = 1; 18 for(int i = first[u]; i != -1; i = e[i].next) { 19 int v = e[i].to; 20 dfs(v); 21 siz[u] += siz[v]; 22 for(int j = siz[u]; j >= 2; j--) 23 for(int k = 1; k <= j && k <= siz[v]; k++) 24 g[u][j] = min(g[u][j], min(f[u][j - k] + e[i].d + g[v][k], g[u][j - k] + 2*e[i].d + f[v][k])); 25 for(int j = siz[u]; j >= 2; j--) 26 for(int k = 1; k <= j && k <= siz[v]; k++) 27 f[u][j] = min(f[u][j], f[v][k] + 2*e[i].d + f[u][j - k]); 28 } 29 return; 30 } 31 32 void add(int u, int v, int w) { 33 e[cnt] = (Edge) {v, first[u], w}; 34 first[u] = cnt++; 35 } 36 37 int main() { 38 while(cin>>n && n) { 39 memset(f, 0x7f, sizeof(f)); 40 memset(g, 0x7f, sizeof(g)); 41 memset(first, -1, sizeof(first)); 42 memset(vis, 0, sizeof(vis)); 43 memset(siz, 0, sizeof(siz)); 44 cnt = 0; 45 for(int u, v, w, i = 1; i < n; i++) { 46 cin>>u>>v>>w; 47 add(v, u, w); 48 vis[u] = 1; 49 } 50 for(int i = 0; i < n; i++) 51 if(!vis[i]) s = i; 52 dfs(s); 53 cin>>q; 54 cout<<"Case "<<++tot<<":"<<endl; 55 for(int i = 1; i <= q; i++) { 56 cin>>x; 57 for(int j = n; j; j--) 58 if(g[s][j] <= x) { 59 cout<<j<<endl; 60 break; 61 } 62 } 63 } 64 return 0; 65 }
以上是关于LA 4015 Cave的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 2049: [Sdoi2008]Cave 洞穴勘测