- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
四川省绵阳南山中学
叶诗富
电话QQ:282364860
;内容简介;树是一种十分优美的数据结构,因为它本身就具有的递归性,所以树和子树之间能相互传递很多信息,树上的许多特征都可以通过它的子树的对应特征计算获得。所以树做动态规划求最优解和做统计非常方便。;树上最长链;目标:如图计算1为根的树上最长链;此题还有两个困难。
1.树的根没有明确给出。没有根我们不能方便的在树上做动规
2.每个节点的最大儿子个数不确定。保存树有一定的麻烦;问题一解决比较简单我们扫描数据,根节点不是任何一个节点的儿子,就可以找出根节点来。
对于问题二的解决。因为真实的父子关系只有N-1个,我们只需开N个空间就可以保存信息,只是我们需另外开两个大小为N的数组,来记录每个节点的儿子个数和开始位。;此题的输入有特殊性,存储问题好解决。
但对于大多数的题目,信息是以边的形式给的且是无序的。
常用邻接表保存(这也是一般图的存储方法)。
大致处理方法如下:
用一个大小为2倍N的链表来记录树上各边的信息,具有相同顶点的边串在一起,再用一个大小为N的数组作为表头,记录每一个点连出的链表开头的位置。这样我们就可以通过表头访问节点出去的每个点了。;方法拓展;没有上司的晚会Ural1039加强;因公司的人际关系为一棵树,假设编号为root的节点是树的根,则问题可以描述成f[root]表示求以root为根的树上能得到的最大气氛和。我们希望用root的儿子的对应信息来推出f[root].
由于节点root 有选和不选两种可能,所以当我们root节点选择时,需要它的子节点不选时的最大值,当root节点不选时,它的子节点选和不选都可以。所以我们需要加半维来表示树的根结点是否选取才能从子树推算出父亲的最大值。;定义状态f[i,j]表示以i为根的树能得到的最大的气氛和,j=0时表示根节点不选,j=1时表示根节点要选。状态转移方程为
F[i,0]=Σmax(f[son,1],f[son,0]);其中son为i的子节点。
F[i,1]= Σf[son,0]+g[i];其中g[i]表示节点i的气氛值。
答案是max(f[root,0],f[root,1]) root为整棵树的根。
时间复杂度为O(N)
空间复杂度为O(N);int DP(int a,int b)
{
if(used[a][b]!=inf) return used[a][b];
used[a][b]=0;
int ans=0;
for(int i=head[a];i;i=f[i].next)
{
int t=DP(f[i].go,0);
if(b==0) t=max(t,DP(f[i].go,1));
ans+=t;
}
ans+=b*d[a];
used[a][b]=ans;
return ans;
};根据上面的分析,利用树的递归性,通过子树的对应信息,推出了树上想要的信息,从而找出了问题的解。;void solve()
{
queueintq;
q.push(root);
int now,p=0;
while (!q.empty()){
now=q.front();q.pop();s[++p]=now;
for (int i=head[now];i;i=nex[i]) q.push(to[i]);}
for (int i=p;i=1;--i){
now=s[i];
for(int j=head[now];j;j=nxt[j]) f[now][0]+=max(f[to[j]][0],f[to[j]][1]);
for(int j=head[now];j;j=nxt[j]) f[now][1]+=f[to[j]][0];
f[now][1]+=val[now];
}};深搜的非递归实现方法如下:
扩展每个节点,将当前儿子节点加入栈并处理,直到其所有儿子节点都已经被处理,就更新其父亲节点并将其弹出栈。
;参考代码:
void DP(int a)
{ S.push(a);
memcpy(head2,head,sizeof(head));
while (!S.empty()) {
int a=S.top();
used[a]=true;
if (head2[a]){ //还有儿子没走
int tal=f[head2[a]].go;
if (!used[tal]) S.push(tal); //儿子未被访问过
文档评论(0)