樹形dp學習
阿新 • • 發佈:2019-01-20
防止 基本 技術分享 父節點 必須 最長路 div cnblogs 們的
學習博客:https://www.cnblogs.com/qq936584671/p/10274268.html
樹的性質:n個點,n-1條邊,任意兩個點之間只存在一條路徑,可以人為設置根節點,對於任意一個節點只存在至多一個父節點,其余為子節點。
記憶化樹形dp模型較為抽象難以理解,以下通過由淺到深的方式解析樹形dp以及樹的性質。
樹形dp求樹的直徑:(在一顆樹裏找到點X,Y,使得|XY|最大)
如圖,我們令A為根節點,令dfs遍歷順序為ABDGHEFC。
在我們的dfs計算過程中,我們從下往上求解每一個節點,總的來說我們要求兩個東西:
1、以每一個節點為根,所能到達的最長路徑dp【u】
2、以每一個節點為根,它下面的的樹的最長路徑ans(其實就是找到 兩個沒有重復路徑的子樹,例如以B為根節點,會找到BDG+BE而不會找到BDG+BDH)
然後將子樹中以子樹根為起點所能到達的最長路徑傳給父節點,最後得出答案
具體看下面代碼:
struct Node { int nex,val; }; vector<Node>node[maxn];//node[u][i].nex代表該節點的子節點 node[u][i].val代表該節點與子節點之間路徑的權值 void dfs(int u,int fa)//該節點和該節點的父親 { for(int i=0;i<node[u].size();i++) { int v=node[u][i].nex; if(v!=fa)//防止回到父節點{ dfs(v,u);// ans=max(ans,d[u]+d[v]+node[u][i].val);//這個必須在下面一步的前面 d[u]=max(d[u],d[v]+node[u][i].val); } } }
理解了基本的樹形dp之後,開始下面的練習:
樹形dp學習