#include using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector>> adj(N + 1); for (int i = 0; i < N - 1; i++) { int u, v; long long w; cin >> u >> v >> w; adj[u].emplace_back(v, w); adj[v].emplace_back(u, w); } // Build a preorder traversal, storing (node, parent). vector> stk; stk.reserve(N); vector> order; order.reserve(N); stk.emplace_back(1, 0); while (!stk.empty()) { auto [u, p] = stk.back(); stk.pop_back(); order.emplace_back(u, p); for (auto &e : adj[u]) { int v = e.first; if (v == p) continue; stk.emplace_back(v, u); } } // dp[u] = max sum of a downward path starting at u (choosing at most one child branch, non-negative) vector dp(N + 1, 0); long long answer = 0; // Process in reverse preorder (i.e., postorder) for (int i = (int)order.size() - 1; i >= 0; --i) { int u = order[i].first; int p = order[i].second; // Find the top two child-contributions long long best1 = 0, best2 = 0; for (auto &e : adj[u]) { int v = e.first; long long w = e.second; if (v == p) continue; long long contrib = dp[v] + w; if (contrib > best1) { best2 = best1; best1 = contrib; } else if (contrib > best2) { best2 = contrib; } } // The best path passing through u uses the two highest branches answer = max(answer, best1 + best2); // For parent's consideration, u contributes only its best single branch dp[u] = best1; } cout << answer << "\n"; return 0; }