码迷,mamicode.com
首页 > 其他好文 > 详细

树形dp

时间:2020-02-26 14:13:48      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:out   形式   nbsp   struct   clu   add   col   记忆化搜索   val   

一般解决方法 根->儿子,再由儿子->根,推出根的值

基本模型:

没有上司的舞会

任意两个一起跳舞的职员层次至少相差2(关系可以看成一棵树,相邻之间不能选择即该节点的父亲和儿子,根节点没有父亲)

一般解法:用f(x)表示x子树进行了决策之后x被选择,能获得的最大权值和,g(x)表示x子树进行了决策之后x没有被选进去,能够得到的最大权值和;

f(x)=(枚举)g(son)+valx,g(x)=(枚举儿子)max{f(son),g(son)}

考虑枚举顺序,先更新儿子。记忆化搜索

#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 6100
struct tree{
    int to,nx;
}edge[maxn];
int head[maxn],cnt,f[maxn],g[maxn],v[maxn],tag,max1;
void add(int u,int v)
{
    edge[++cnt].nx=head[u];
    edge[cnt].to=v;
    head[u]=cnt;
}
void dfs(int x)
{
    f[x]=v[x];
    for(int i=head[x];i;i=edge[i].nx)
    {
        if(edge[i].to!=x){
            dfs(edge[i].to);
            f[x]+=g[edge[i].to];
            g[x]+=max(g[edge[i].to],f[edge[i].to]);
        }
    }
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>v[i];
    for(int i=1;i<=n;i++)
    {
        int u,v;
        cin>>v>>u;
        if(i==n-1) tag=u;
        add(u,v);
    }
    dfs(tag);
    max1=max(g[tag],f[tag]);
    cout<<max1;
    return 0;
}

求树的重心(题目是以图的形式给的)

对于一根n个节点的无根树,找到一个点A,使得把树变成以该点为根的有根树时,最大子树的结点树最小。A叫做重心。

求一下每个点子树的点数,再考虑当其作为重心时,最大子树的结点数,和当前重心进行比较;

记忆搜索:
void
dfs(int x,int fa)//fa指的是x的父亲 { int t=0;siz[x]=1;//只有一个x节点时,长度为1 for(int i=head[x];i;i=edge[i].nx) { if(edge[i].to!=fa) { dfs(edge[i].to,x);//遍历每个子节点 siz[x]+=siz[edge[i].to]; t=max(t,siz[edge[i].to]);//t记录最大子树的结点数 } t=max(t,n-siz[x]); //比较fa另一侧的子树结点数与当前最大结点数 if(mx>t) { mx=t,poi=x; } } }

树的直径

树的直径是树当中最长的一条链

void dfs(int x,int fa)//fa指的是x的父亲
{
    for(int i=head[x];i;i=edge[i].nx)
    {
        if(edge[i].to!=fa)
        {
            int v=edge[i].to;
            dfs(edge[i].to,x);//遍历每个子节点
            if(dp[0][v]+w[v]>dp[0][x])//dp[0][x]代表以0为节点的最长链,1为次长链            {
                dp[1][x]=dp[0][x];//进行更新,因为一个点只遍历一次,所以最长链上的节点与次长链上的结点不会重合
                dp[0][x]=dp[0][v]+w[v];
            }
            else if(dp[0][v]+w[v]>dp[1][x])
                dp[1][x]=dp[0][v]+w[v];
        } 
      
    }
   ans=max(ans,dp[1][x]+dp[0][x]);
   return;
}

 

树形dp

标签:out   形式   nbsp   struct   clu   add   col   记忆化搜索   val   

原文地址:https://www.cnblogs.com/Showend/p/12359086.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!