我是靠谱客的博主 阳光吐司,这篇文章主要介绍【树形DP】Gym101667A Broadcast Stations,现在分享给大家,希望可以做个参考。

Souce:2017-2018 ACM-ICPC, Asia Daejeon Regional Contest
Problem:
一棵5e3的树,可以选择一些点放上基站,如果u上的基站价值为d,那么距离u小于等于d的点都会被覆盖,问使得整棵树被覆盖的最小价值。
Idea:
g [ u ] [ j ] g[u][j] g[u][j]表示u点这颗子树里距离u点大于j的点都被覆盖的最小价值。
显然 g [ u ] [ j ] = ∑ g [ v ] [ j − 1 ] ( j > 0 ) g[u][j] = sum g[v][j-1] (j gt 0) g[u][j]=g[v][j1](j>0)
f [ u ] [ j ] f[u][j] f[u][j]表示将u点这颗子树全覆盖,并且这颗子树外距离u点小于等于d的点都被覆盖的最小价值。那么要么由子树传递,要么自己放上价值为j的基站。
f [ u ] [ j ] = m i n ( f [ v ] [ j + 1 ] − g [ v ] [ j ] , j ) + g [ u ] [ j + 1 ] f[u][j] = min(f[v][j+1]-g[v][j], j)+g[u][j+1] f[u][j]=min(f[v][j+1]g[v][j],j)+g[u][j+1]
最后得到 g [ u ] [ 0 ] = f [ u ] [ 0 ] g[u][0] = f[u][0] g[u][0]=f[u][0]
Code:

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int N = 5e3+10;
const int INF = 0x3f3f3f3f;
int n, f[N][N], g[N][N];
vector<int> G[N];
void dfs(int u, int fa) {
for(int v:G[u]) if(v != fa) {
dfs(v, u);
for(int i = 1; i <= n; i++) g[u][i] += g[v][i-1];
}
g[u][0] = n; f[u][n] = n;
for(int i = n-1; i >= 0; i--) {
f[u][i] = min(max(1, i)+g[u][max(1, i)+1], f[u][i+1]);
for(int v:G[u]) if(v != fa)
f[u][i] = min(f[u][i], f[v][i+1]+g[u][i+1]-g[v][i]);
}
g[u][0] = f[u][0];
for(int i = 1; i <= n; i++) g[u][i] = min(g[u][i], g[u][i-1]);
}
int main() {
scanf("%d", &n);
for(int i = 1; i < n; i++) {
int u, v; scanf("%d%d", &u, &v);
G[u].pb(v); G[v].pb(u);
}
dfs(1, 0);
printf("%dn", g[1][0]);
return 0;
}

最后

以上就是阳光吐司最近收集整理的关于【树形DP】Gym101667A Broadcast Stations的全部内容,更多相关【树形DP】Gym101667A内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部