ACM-11月19日周日周末训练心得
来源:互联网 发布:大数据人才需求 编辑:程序博客网 时间:2024/05/29 18:27
这周看了树形DP的一些博客,比如一道compuer的题目要去求树上每个点的最远距离是多少,这题一直被称为树形dp的经典是有它的道理的,因为树dp就是把dp放到树上做了,一般是从上到下或从下到上(利用回溯)的移转状态而这题很合适的需要两次dfs。对于<u,v>(有向),dp[u][0]表示在u的子树下u的最远距离是多少dp[u][1]表示在u的子树(和dp[u][0]不是同一孩子)u的次远距离是多少dp[u][2]表示通过u的父亲能走的最远距离是多少第一次从下到上,对于<u,v>(有向),状态转移显然是 dp[u][0] = dp[v][0]+w[i];所以要先算出dp[v][0]才能知道dp[u][0]。故是从下往上。第二次从上往下,其实就是再遍历一边图,把dp[v][2]算出来,显然:dp[v][2] = max(dp[u][2],dp[v][0]+w[i]==dp[u][0]?dp[u][1]:dp[u][0]) + w[i];要算dp[v][2],要先算dp[u][0],所以从上往下。最后的答案就是 max(dp[u][0],dp[u][2])。
void dfs1(int u,int v) //每个节点子树下的最大和次大 { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; dfs1(v,u); int w=edge[i].w; int temp = dp[v][0] + w; if(temp >= dp[u][0]) { dp[u][1]=dp[u][0]; dp[u][0] = temp; } else if(temp > dp[u][1]) dp[u][1] = temp; } } void dfs2(int u,int v) { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(dp[u][0] == dp[v][0] + edge[i].w) { dp[v][2] = max(dp[u][2],dp[u][1]) + edge[i].w; } else { dp[v][2] = max(dp[u][2],dp[u][0]) + edge[i].w; } dfs2(v,u); } }对于HDU1520,给一棵树,选最多的结点使得选择的结点不存在直接的父子关系,很容易想到一个结点有两个状态:选或者不选
,所以自然地想到状态dp[u][0/1]表示u子树内的最佳答案,u的状态为选或者不选,初始化自然是叶子结点dp[u][0]=0,dp[u][1]=w[u],转移则可以考虑依次考虑,u不选的时候:u的儿子可以任意选或者不选,所以dp[u][0]+=max(dp[v][0],dp[v][1]),u选的时候:u的儿子必定不能选,所以dp[u][1]+=dp[v][0] 然后dp[u][1]+=w[u]表示加上u这个点,答案自然就是max(dp[rt][0],dp[rt][1])了。
阅读全文
0 0
- ACM-11月19日周日周末训练心得
- ACM-11月5日周日周末训练心得
- ACM-11月12日周日周末训练心得
- ACM-11月26日周日周末训练心得
- ACM-9月3日周日周末训练心得
- ACM-9月17日周日周末训练心得
- ACM-9月24日周日周末训练心得
- ACM-10月1日周日周末训练心得
- ACM-10月15日周日周末训练心得
- ACM-12月3日周日周末训练心得
- ACM-12月10日周日周末训练心得
- ACM10月29日周日周末训练心得
- ACM-10月8日周日周末训练日记
- ACM-9月10日周末训练心得
- ACM训练周末总结—11月19日
- ACM训练半周日记—11月9日
- ACM训练周末总结—11月5日
- ACM训练周末总结—11月12日
- Python机器学习之决策树案例
- Retrofit+RxJava+Mvp实现多线程视频下载
- 安徽籍巨型计算机之父—慈云桂
- VS快捷键
- JPA之JPA中的一对多双向关联
- ACM-11月19日周日周末训练心得
- 新公司新入手的一个新项目的心路历程
- java排序算法(持续更新)
- 2017.11.19
- 二级列表实现购物车的效果
- CentOS 6.5下MySQL 5.7.20主从复制架构配置
- linux(vi)常用命令
- Dijkstra(邻接表+优先队列)
- 仿QQ空间打赏功能实现