#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
#include "debug.h"
#else
#define DEBUG(...)
#endif

#define size(v) v.size()

template <class T = int> struct tree {
  struct edge {
    int from, to;
    T w;
    int operator-(int v) const { return from ^ to ^ v; }
  };
  int n;
  vector<edge> es;
  vector<vector<int>> g;
  vector<int> pv, pe, sz, dep, vs, in, out, head;
  vector<T> dist;
  tree(int _n = 0) : n(_n), g(n) {}
  void add(int u, int v, T w = 1) {
    g[u].push_back(size(es)), g[v].push_back(size(es));
    es.push_back({u, v, w});
  }
  void dfs(int v) {
    sz[v] = 1;
    for (int id : g[v]) {
      if (id == pe[v]) continue;
      int to = es[id] - v;
      assert(pv[to] == -1);
      pv[to] = v, pe[to] = id;
      dep[to] = dep[v] + 1, dist[to] = dist[v] + es[id].w;
      dfs(to);
      sz[v] += sz[to];
    }
    sort(begin(g[v]), end(g[v]), [&](int a, int b) {
      return sz[es[a] - v] * (a != pe[v]) > sz[es[b] - v] * (b != pe[v]);
    });
  }
  void build(int r = 0) {
    assert((int)size(es) == n - 1);
    pv.assign(n, -1), pe.resize(n), sz.resize(n), dep.resize(n), dist.resize(n);
    pe[r] = -1, dep[r] = 0, dist[r] = 0;
    dfs(r);
  }
  void dfs_hld(int v) {
    in[v] = size(vs), vs.push_back(v);
    for (int id : g[v]) {
      if (id == pe[v]) continue;
      int to = es[id] - v;
      head[to] = to == es[g[v][0]] - v ? head[v] : to;
      dfs_hld(to);
    }
    out[v] = size(vs);
  }
  void build_hld(int r = 0) {
    build(r);
    vs.clear(), in.resize(n), out.resize(n), head.resize(n);
    head[r] = r;
    dfs_hld(r);
  }
  bool anc(int u, int v) const { return in[u] <= in[v] and out[v] <= out[u]; }
  int lca(int u, int v) const {
    while (true) {
      if (in[u] > in[v]) swap(u, v);
      if (head[u] == head[v]) return u;
      v = pv[head[v]];
    }
  }
  int len(int u, int v) const { return dep[u] + dep[v] - 2 * dep[lca(u, v)]; }
  T d(int u, int v) const { return dist[u] + dist[v] - 2 * dist[lca(u, v)]; }
  int la(int v, int d) const {
    assert(0 <= d and d <= dep[v]);
    while (dep[head[v]] > d) v = pv[head[v]];
    return vs[in[head[v]] + (d - dep[head[v]])];
  }
  int next(int from, int to) const {
    assert(from != to);
    if (not anc(from, to)) return pv[from];
    return la(to, dep[from] + 1);
  }
  vector<pair<int, int>> ascend(int from, int to) const {
    vector<pair<int, int>> res;
    while (head[from] != head[to]) {
      res.emplace_back(in[from], in[head[from]]);
      from = pv[head[from]];
    }
    if (from != to) res.emplace_back(in[from], in[to] + 1);
    return res;
  }
  vector<pair<int, int>> descend(int from, int to) const {
    if (from == to) return {};
    if (head[from] == head[to]) return {{in[from] + 1, in[to]}};
    auto res = descend(from, pv[head[to]]);
    res.emplace_back(in[head[to]], in[to]);
    return res;
  }
  template <class F> void run(int from, int to, F f, bool vertex = true) const {
    int v = lca(from, to);
    for (auto e : ascend(from, v)) f(e.first + 1, e.second);
    if (vertex) f(in[v], in[v] + 1);
    for (auto e : descend(v, to)) f(e.first, e.second + 1);
  }
};

template <class Node, class T> auto tree_dp(tree<T>& g, int r = 0) {
  g.build_hld(r);
  vector<Node> lower(g.n - 1), upper(g.n - 1), all(g.n);
  vector<vector<Node>> cum(g.n);
  for_each(rbegin(g.vs), rend(g.vs), [&](int v) {
    int m = size(g.g[v]) - (v != r);
    cum[v].resize(m + 1);
    for (int i = m; i--; ) cum[v][i] = lower[g.g[v][i]] + cum[v][i + 1];
    if (v != r) lower[g.pe[v]] = cum[v][0].add(v, g.es[g.pe[v]]);
  });
  for (int v : g.vs) {
    Node cur = v != r ? upper[g.pe[v]] : Node();
    for (int i = 0; i < (int)size(cum[v]) - 1; ++i) {
      upper[g.g[v][i]] = (cur + cum[v][i + 1]).add(v, g.es[g.g[v][i]]);
      cur = cur + lower[g.g[v][i]];
    }
    all[v] = cur.add(v);
  }
  return make_tuple(lower, upper, all);
}
struct node {
  int farthest;
  node operator+(const node& b) const {
    node c;
    c.farthest = max(farthest, b.farthest);
    return c;
  }
  node add(int v) const {
    return *this;
  }
  template <class Edge> node add(int v, const Edge& e) const {
    node a = *this;
    a.farthest += e.w;
    return a;
  }
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  tree<int> g(n);
  for (int i = 0; i < n - 1; ++i) {
    int u, v, w;
    cin >> u >> v >> w;
    g.add(u, v, w);
  }
  vector<node> lower, upper, all;
  tie(lower, upper, all) = tree_dp<node>(g);
  int res = 0;
  for (int v = 0; v < n; ++v) {
    array<int, 2> a{-1, -1};
    auto add = [&](int x) {
      if (x > a[0]) {
        a[1] = a[0];
        a[0] = x;
      } else if (x > a[1]) {
        a[1] = x;
      }
    };
    for (int id : g.g[v]) {
      if (id == g.pe[v]) {
        add(upper[id].farthest);
      } else {
        add(lower[id].farthest);
      }
    }
    res = max(res, a[0] + a[1]);
  }
  cout << res << '\n';
}



Measured memory_bytes: 24988