LA 4015 Cave

时间:2020-02-18
本文章向大家介绍LA 4015 Cave,主要包括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 }
View Code

原文地址:https://www.cnblogs.com/ympc2005/p/12326550.html