AcWing 3760. 最大剩餘油量(樹的最長路徑)
阿新 • • 發佈:2021-07-18
題目
一個國家由 n 個城市組成,這 n 個城市由 n−1 條雙向道路連線,呈一個樹形結構。
每個城市都設有加油站,在第 i 個城市可以購買 wi 升汽油。
汽車在道路上行駛,毫無疑問也會消耗汽油,每條道路的具體耗油量也會給出。
現在,需要制定一條汽車的行進路線,從任意城市 s 出發,經過一條簡單路徑,到達任意城市 e 結束。
注意,行進路線也可以只包含一個城市(也就是哪都沒去)。
汽車初始時油箱是空的,但是可以在路線中經過的每個城市購買汽油,包括開始城市和最終城市。
如果在一條行進路線中,汽車沿一條道路從某一城市開往另一城市時,現有油量小於該條道路所需油量,那麼就說明這條行進路線行不通。
請問,在保證行進路線合理的情況下,汽車在抵達最終城市後,可以剩餘的最大油量是多少?
再次提醒,汽車在最終城市也可以加油。
輸入輸出
輸入:第一行包含整數 n。
第二行包含 n 個整數 w1,w2,…,wn。
接下來 n−1 行,每行包含三個整數 u,v,c,表示城市 u 和城市 v 之間存在一條雙向道路,耗油量為 c。
輸出:一個整數,表示可能的最大剩餘油量。
思路
這道題是選出一條路徑使最大剩餘油量最大,即樹的最長路徑(樹的直徑)問題。點權為正,邊權為負。
可以列舉一條路徑的最高點,該點的最長路徑由根節點的點權+子樹的最長長度+子樹的次長長度。用遞迴來做,遞迴返回的是子樹往下的最長長度,計算出後,更新最長路徑長度。寫的太混亂了
作者:inss!w! 出處:https://www.cnblogs.com/Hfolsvh/ 版權宣告:本部落格所有文章除特別宣告外,均採用 BY-NC-SA 許可協議。轉載請註明出處!#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 300010; typedef long long LL; int tot; int head[N << 1],ver[N << 1], nxt[N << 1],edge[N << 1]; int w[N]; LL ans; void add(int u, int v, int c) // 新增一條邊a->b { ver[++tot] = v; nxt[tot] = head[u]; head[u] = tot; edge[tot] = c; } LL dfs(int u,int fa){ LL max1=0,max2=0; //以u為根節點的子樹中最大的長度和次大的長度 for(int i = head[u];i;i = nxt[i]){ int v = ver[i]; if(v == fa) continue; LL d = dfs(v,u); //d是以v為根節點的子樹的最長路徑 if(d < edge[i]) continue; d -= edge[i]; //走子樹到根節點需要耗費油量 if(d >= max1) max2 = max1,max1 = d; //先更新max2,再更新max1 else if(d > max2) max2 = d; } ans = max(ans, max1 + max2 + w[u]); return max1 + w[u]; //返回的是以u為根節點的最長路徑 } int main() { int n; cin >> n; for (int i = 1; i <= n; i ++ ) cin >> w[i]; for (int i = 0; i < n-1; i ++ ){ int u,v,c; cin >> u >> v >> c; add(u, v, c); add(v, u, c); } dfs(1,0); cout << ans; }