多校第一场 1003
来源:互联网 发布:软件作者权 编辑:程序博客网 时间:2024/05/18 00:52
炸弹
题目描述:
一个树,n~1e5个点,每个点有一个权值,表示可以如果炸掉它,就可以免费炸掉距离他小于等于w[i]的点.每个点的权值<=100; 问最少炸几个可以全部炸完.
题解:
首先是一个点有一定范围的树上的dp.以前做过的是可以开二维dp[i][j],i是被j点控制的,j不限于i的子树. 但是这道题不能开二维,但是因为权值小于等于100,所以 用g[i][j]表示i为根的子树,从外面获取了炸到i的fa j的长度的权利. i点是1,i的儿子是2…. 这样j=0就是没有外界提供. 考虑转移g[i][j]:对于儿子v, 并不是单纯的g[v][j-1],而是对于v来说,从外界获取的小于等于j-1的g, 以及v可以向外面扩充的所有的j.(因为并不一定缺恰好i-1最好,我们先定义的都是恰好,可能反倒向外扩充一个东西更好). 所以我们要额外维护一个f[u][i],表示的是可以向外扩充i的距离的最小值.这样我们再根据实际重新定义下:f[u][i]指u点向外扩充大于等于i的最小值,g[u][i]表示u点从fa需要获取的小于等于i的长度的最小值,可能也往外放,(只要小于等于获取的值就行). 这样怎么转移? f[u][i]是横叉dp过去,强制当前的是要提供i的,其他的都用g[i]就行. g[u][i]每一个点都用g[v][i-1]. 然后重点来了,我们这样算出来的是恰好值,需要每一个点算完之后 都弄成实际意义的小于等于的值.
重点:
(1)树上一个点有控制范围.多开一维描述范围.
(2)g不够用,想明白恰好和满足限制下最小值的区别,额外增加f
(3)f和g的转移,之后再取最值.
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <ctype.h>#include <limits.h>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <map>#include <stack>#include <set>#include <bitset>#define CLR(a) memset(a, 0, sizeof(a))#define REP(i, a, b) for(int i = a;i < b;i++)#define REP_D(i, a, b) for(int i = a;i <= b;i++)typedef long long ll;using namespace std;const int maxn = 1e5 + 10;const int maxDist = 100+10;const int INF = 1e8+100;int n, w[maxn];vector<int> G[maxn];int f[maxn][maxDist], g[maxn][maxDist];void dfs(int u, int fa){ REP(i, 0, G[u].size()) { int v = G[u][i]; if(v!=fa) { dfs(v, u); } } for(int i = 0;i<=100;i++) { f[u][i] = INF; int a, b; if(w[u]>=i) { b = 1; } else { b = INF; } a = 0; REP(j, 0, G[u].size()) { int v = G[u][j]; if(v!=fa) { int t = f[v][i+1];//简单的横叉转移 //int t_min = min(m_g[v][i], m_f[v][i+1]); if(t!=INF) { b = min(b+g[v][i] , a+t); } else { b = b + g[v][i]; } a += g[v][i]; } } f[u][i] = b; g[u][i] = INF;//g的转移也很简单 if(i>=1) { a = 0; } else { a = 1; } REP(j, 0, G[u].size()) { int v = G[u][j]; if(v!=fa) { int limit = max(0, i-1); int t = g[v][limit]; //t = min(t,m_f[v][100]); a += t; } } g[u][i] = a; } f[u][101] = INF; g[u][101] = INF; for(int i = 100;i>=0;i--)//关键理解:我们定义的f和g有实际意义. { f[u][i] = min(f[u][i], f[u][i+1]); } g[u][0] = min(g[u][0], f[u][0]); for(int i = 1;i<=100;i++) { g[u][i] = min(g[u][i], g[u][i-1]); }// for(int i = 0;i<=3;i++)// {// printf("u is %d i is %d f is %d g is %d\n", u, i, f[u][i], g[u][i]);// }}void solve(){ dfs(1, 0); printf("%d\n", g[1][0]);}int main(){ freopen("3Cin.txt", "r", stdin); //freopen("3Cout.txt", "w", stdout); while(scanf("%d", &n) != EOF) { REP_D(i, 1, n) { scanf("%d", &w[i]); } REP_D(i,1,n) { G[i].clear(); } REP_D(i, 1, n-1) { int a, b; scanf("%d%d", &a, &b); G[a].push_back(b); G[b].push_back(a); } solve(); } return 0;}
0 0
- 多校第一场 1003
- 多校第一场
- 多校联赛第一场
- 2013多校第一场
- 2013 多校第一场
- 多校第一场1006
- 多校第一场1010
- 2016多校第一场
- hdu 4602(2013多校联赛第一场1003)
- 2015多校第一场1003 hdu 5290 Bombing plan
- HDU6035 2017多校第一场1003 树形DP
- 多校第一场:hdu 4308(bfs)
- 2013多校第一场 - from lanshui_Yang
- hdu 4602 Partition 多校第一场
- hdu 4604 Deque 多校第一场
- 杭电2013多校第一场
- 多校第一场Couple doubi
- 2014多校联合第一场
- html5.0与html4的“区别”
- maven+springMVC+mybatis+junit详细搭建过程
- 计算机中的墨菲定律
- 正则表达式匹配手机的几种写法
- Linux kernel 分析之十九:阅读源代码技巧-变量命名规则
- 多校第一场 1003
- Buildings
- 原生 or 混合 ? 关于应用永不停息的争论
- OX01: Web Speder 入门
- 使用 ALinq 实现 Linq to MySQL【转】
- 阅读《C陷阱与缺陷》的知识增量
- 如何用jquery写一个简单的返回顶部
- eclipse中SVN分支合并到主干
- String,StringBuffer,StringBuilder比较