【感想1】:嘛。。今天终于能把讲的内容稍微写下代码了。。。
Computer(HDU2196)
给出一个n个节点的树,求出到每个点最远的点到它的距离。
【思路】
1、直接从每个点出发搜索到他最远的那个点。总复杂度O(n^2)。
2、利用树的特殊性质,树形dp,复杂度 O(n)。
那么怎么dp呢?
我们以任意一点作为根把整棵树提起来。一个点到他最远的点只有两种可能:
1、这个点在它的子树内部。
2、这个点不在它的子树内部。
所以,我们要dp两次,每次分别解决其中一种情况。
我们设dp1[i]表示以i为根,最远点在子树内部的最远距离转移时,考虑一个点u,再考虑它的所有儿子vdp1[u]=max(dp1[v]+1)。如果这是一棵带权树,就加上相应的边权值w。dp1[u]=max(dp1[v]+w)
那么在子树外呢?
用dp2[i]表示第i个点到不在它子树内部点的最远距离。
这里也是只有两种情况:
1、这一点在它父亲的某一颗子树中。
2、这一点不在它父亲的子树中。
对于第一种情况:
考虑一个点u,和他的父亲fa。我们找到Fa所有儿子中的最大值mx和次大值mxx。如果dp1[u]=mx 则dp2[u]=w+mx,否则dp2[u]=w+mxx
对于第二种情况:
直接用fa的dp2值去转移
dp2[u]=dp2[fa]+1
两边dp跑完之后,每个点的答案就是
max(dp1,dp2)
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
【代码】:然而代码呢?。。。不好意思,还没写,只说能写而已
树的直径
树直径的定义为一棵树上距离最远的两个点之间的距离。
其实我们刚才的dp也顺便解决了这个问题,就是所有点答案的最大值。
求直径更常用的方法是在树上随便找一个点,做一遍bfs,求出到他最远的点。再任取一个到他最远的点,从这点出发,再做bfs,到这一点最远的距离就是直径。
House of Representatives(Gym 100496H)
给出一个有边权和点权的树,第i个点的权值为p[i]。
现在我们要选出一些点,选每个点都有对应的代价,
选出第i个点的代价为:
选出一个点,最小化代价
【思路】:
本题的解法和上一题类似,也是把代价分成两个部分。
dp1[i]表示选第i个点,只考虑i所在的子树,最小代价是多少。
sum[j]表示j这棵子树的权值和,wij为i到j的边权,j是i的所有儿子节点。
现在考虑第二种情况。
设u是v的父亲,我们考虑从u向v转移的过程:
1是根节点,j枚举u的所有儿子。