算法提高课-动态规划-树形DP-AcWing 1072. 树的最长路径:dfs写法
生活随笔
收集整理的這篇文章主要介紹了
算法提高课-动态规划-树形DP-AcWing 1072. 树的最长路径:dfs写法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目分析
來源:acwing
分析:
樹的最長直徑:距離最遠的兩個點之間的距離,這里是帶邊權的情況。
在沒有邊權(或者邊權都是1)的時候,樹的直徑也是最遠兩個點的距離。
樣例對應的樹如下,樹的直徑= 22,對應的最長鏈是下面橘黃色的那條路徑。
經典做法:
這里把路徑分類,要找出路徑中最高的點。經過一個點A的所有路徑中,最高點是A點的路徑歸類到A點門下。
這樣我們就可以枚舉所有點,找到掛到該點上的路徑的最大值即可。
接下來的問題是:如何求掛到該點上所有路徑中的最大值(最長路徑)呢?
這個問題的思路是:對于結點A上的所有路徑,我們找到A點的所有直接兒子,分別求它們從上往下的最大距離(到葉子結點)。我們只需要其中的最大值和次大值,記為d1和d2,則,A點的路徑長度最大值就是 d1 + d2,因為它們直接構成以A為最高點的最長路徑的長度。以下圖為例,1作為最高點,構成的最長路徑一定是從它的3個兒子中任意選擇兩個構成的。
ac代碼
dfs寫法
#include<bits/stdc++.h> using namespace std; const int N = 10010, M = N * 2; int n; int h[N], e[M], ne[M], w[M], idx; int ans; // 樹的直徑存在ans中void add(int a, int b, int c){e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; }// 以u點為最高點,返回從該點往下走的路徑的最大長度 // father防止反向遍歷,即從低到高,進入循環 int dfs(int u, int father){int dist = 0; // 從u點開始往下走的最大長度int d1 = 0, d2 = 0; //最長距離和次長距離// 遍歷所有兒子結點for(int i = h[u]; ~i; i = ne[i]){int j = e[i];// 由于是無向邊,這里防止反向搜索if(j == father) continue;int d = dfs(j,u) + w[i];dist = max(dist, d);// 如果d大于最大值d1,則最大值d1變成次大值if( d >= d1) d2 = d1, d1 = d;// 否則d如果大于次大值,則d就是次大值else if(d > d2) d2 = d;}ans = max(ans, d1 + d2);return dist; }int main(){cin >> n;memset(h, -1, sizeof h);for(int i = 0; i < n -1; i ++){int a, b, c;cin >> a >> b >> c;add(a, b, c), add(b, a ,c);}dfs(1, -1); // 任取結點作為根結點,這里選擇1號點cout << ans << endl;}題目來源
https://www.acwing.com/problem/content/1074/
總結
以上是生活随笔為你收集整理的算法提高课-动态规划-树形DP-AcWing 1072. 树的最长路径:dfs写法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSP认证 201503-3节日[C++
- 下一篇: CSP认证201503-4网络延时[C+