2021-7-21 又回到树形dp的恐怖世界www

Posted KaaaterinaX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-7-21 又回到树形dp的恐怖世界www相关的知识,希望对你有一定的参考价值。

树形dp就是在一棵树上跑动态规划,通常用到dfs等方法实现。

这篇博客就是记录我刷的树形dp,刷题路线参考了y总的课程以及聚聚的博客:【DP_树形DP专辑】

一、常规树形dp

1、求树的中心
树的中心是树上的一个节点,这个节点在距离其他节点的最长路径最短。
这个非常非常基础,同时在很多较复杂的题目中需要用到这个方法解决降低复杂度。
思路分析:
任意选一节点作为根节点
对于任意一个节点,距离它最远的节点有两种情况:
1⃣️最远的节点经过父节点
2⃣️最远的节点不经过父节点
继续观察第1⃣️种情况,可以发现最大距离可能由父节点的(A.最长路径)或者(B.次长路径)更新(如果父节点的最长路径经过该节点则由次长路径更新)。
代码实现:


2、树的最长路径(含负边权)
思路分析:
如何划分状态?如何更新ans?
选任意点作为树根(因为是无向树)。
计算每一个以该节点作为最高点的路径,以此更新ans。
那么如何计算以该节点作为最高点的路径呢?————找到除了经过其父节点的最大和次大距离,按顺序dfs即可。
代码实现:

const int maxn=1e4+7;
struct ed{
    int to;
    int w;
};
vector<ed> mp[maxn];

int ans=0;//记录答案
int dfs(int u,int fa){
    //标记father,防止再次回到father节点
    //dfs函数return的是该节点走到底的最长路径
    int d1=0,d2=0;//记录最大和次大节点
    int dist=0;
    //cout<<"u="<<u<<endl;
    for(int i=0;i<mp[u].size();i++){
        int to=mp[u][i].to;
        if(to!=fa){
            int d=dfs(to,u)+mp[u][i].w;
            dist=max(dist,d);
            if(d>=d1){
                d2=d1;
                d1=dist;
            }
            else if(d>=d2){
                d2=d;
            }
        }
    }
    ans=max(ans,d1+d2);
    return dist;
}
int main(){
    int n;
    cin>>n;
    
    for(int i=1;i<=n-1;i++){
        int a,b,c;
        cin>>a>>b>>c;
        mp[a].pb({b,c});
        mp[b].pb({a,c});
    }
    dfs(1,-1);
    cout<<ans<<endl;
}

3、

二、树上背包问题

1、二叉苹果树

二叉苹果树

三、树上删边或节点问题

以上是关于2021-7-21 又回到树形dp的恐怖世界www的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2159 Crash 的文明世界 —— 第二类斯特林数+树形DP

BZOJ-3572世界树 虚树 + 树形DP

POJ-2486 Apple Tree (树形DP)

20191110luogu3698小Q的棋盘 | 树形背包dp | 贪心

[树形dp][组合数] JZOJ P1794 保镖排队

BZOJ3572 [Hnoi2014]世界树 虚树 + 树形dp