标签:int 最小花费 需要 char mes bsp print read 动态规划
树上的动态规划
对于一棵子树内的守卫,也可以覆盖子树外的节点,需要加一维来记录子树与外界的关系。
g[u][j] 表示覆盖完子树并且还可以覆盖离子树根节点距离不大于j的点的最小花费
f[u][j] 表示子树内只保证距离子树根节点距离不小于j的节点被覆盖的最小花费
讨论树的子树对于树的关系来转移:
u是v的父亲,则
g[u][j]=min(g[u][j]+f[v][j],g[v][j+1]+f[u][j+1])
f[u][j] = Σf[v][j-1]
g[u][j] = min(g[u][j], g[u][j+1])
f[u][j] = min(f[u][j], f[u][j-1])
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int N = 5e5 + 5, M = 25; 5 6 int n, d, cnt, first[N], w[N], f[N][M], g[N][M], m, inf = 1e9; 7 bool vis[N]; 8 struct Edge { 9 int to, next; 10 } e[N<<1]; 11 12 void dfs(int u, int fa) { 13 if(vis[u]) f[u][0] = g[u][0] = w[u]; 14 for(int i = 1; i <= d; i++) g[u][i] = w[u]; 15 g[u][d + 1] = inf; 16 for(int i = first[u]; i != -1; i = e[i].next) { 17 int v = e[i].to; 18 if(v == fa) continue; 19 dfs(v, u); 20 for(int j = 0; j <= d; j++) 21 g[u][j] = min(g[u][j] + f[v][j], g[v][j + 1] + f[u][j + 1]); 22 for(int j = d; j >= 0; j--) g[u][j] = min(g[u][j], g[u][j + 1]); 23 f[u][0] = g[u][0]; 24 for(int j = 1; j <= d; j++) 25 f[u][j] += f[v][j - 1]; 26 for(int j = 1; j <= d; j++) 27 f[u][j] = min(f[u][j], f[u][j - 1]); 28 } 29 } 30 31 void add(int u, int v) { 32 e[cnt] = (Edge) {v, first[u]}; 33 first[u] = cnt++; 34 } 35 36 int Read() { 37 int f = 1, res = 0; 38 char ch = getchar(); 39 while(ch > ‘9‘ || ch < ‘0‘) { 40 if(ch == ‘-‘) f =- 1; 41 ch = getchar(); 42 } 43 while(ch >= ‘0‘ && ch <= ‘9‘) { 44 res = res*10 + ch - ‘0‘; 45 ch = getchar(); 46 } 47 return res*f; 48 } 49 50 int main() { 51 n = Read(); d = Read(); 52 memset(first, -1, sizeof(first)); 53 for(int i = 1; i <= n; i++) 54 w[i] = Read(); 55 m = Read(); 56 for(int i = 1; i <= m; i++) 57 vis[Read()] = 1; 58 for(int i = 1, u, v; i < n; i++) { 59 u = Read(); v = Read(); 60 add(u, v); add(v, u); 61 } 62 dfs(1, 0); 63 printf("%d\n", f[1][0]); 64 return 0; 65 }
标签:int 最小花费 需要 char mes bsp print read 动态规划
原文地址:https://www.cnblogs.com/ympc2005/p/12307186.html