#include <bits/stdc++.h>
// clang-format off
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wsign-conversion"

#define NDEBUG
using i32 = int32_t;
using i64 = int64_t;
using u32 = uint32_t;
using u64 = uint64_t;
using uint = unsigned int;
using usize = std::size_t;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
template<typename T> constexpr T popcount(const T u) { return u ? static_cast<T>(__builtin_popcountll(static_cast<u64>(u))) : static_cast<T>(0); }
template<typename T> constexpr T log2p1(const T u) { return u ? static_cast<T>(64 - __builtin_clzll(static_cast<u64>(u))) : static_cast<T>(0); }
template<typename T> constexpr T msbp1(const T u) { return log2p1(u); }
template<typename T> constexpr T lsbp1(const T u) { return __builtin_ffsll(u); }
template<typename T> constexpr T clog(const T u) { return u ? log2p1(u - 1) : static_cast<T>(u); }
template<typename T> constexpr bool ispow2(const T u) { return u and (static_cast<u64>(u) & static_cast<u64>(u - 1)) == 0; }
template<typename T> constexpr T ceil2(const T u) { return static_cast<T>(1) << clog(u); }
template<typename T> constexpr T floor2(const T u) { return u == 0 ? static_cast<T>(0) : static_cast<T>(1) << (log2p1(u) - 1); }
template<typename T> constexpr bool btest(const T mask, const usize ind) { return ((static_cast<u64>(mask) >> ind) & static_cast<u64>(1)); }
template<typename T> constexpr T bcut(const T mask, const usize ind) { return ind == 0 ? static_cast<T>(0) : static_cast<T>((static_cast<u64>(mask) << (64 - ind)) >> (64 - ind)); }
template<typename T> bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template<typename T> bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
constexpr unsigned int mod                  = 1000000007;
template<typename T> constexpr T inf_v      = std::numeric_limits<T>::max() / 4;
template<typename Real> constexpr Real pi_v = Real{3.141592653589793238462643383279502884};


class xoshiro
{
private:
    using result_type = uint32_t;
    result_type s[4];
    static result_type rotl(const result_type x, const int k) { return (x << k) | (x >> (32 - k)); }

public:
    xoshiro() : xoshiro(std::random_device{}()) {}
    xoshiro(uint64_t seed)
    {
        uint64_t z = 0;
        for (int i = 0; i < 4; i++) { z = (seed += 0x9e3779b97f4a7c15), z = (z ^ (z >> 33)) * 0x62A9D9ED799705F5, z = (z ^ (z >> 28)) * 0xCB24D0A5C88C35B3, s[i] = static_cast<result_type>(z >> 32); }
    }
    result_type operator()()
    {
        const result_type result = rotl(s[1] * 5, 7) * 9, t = s[1] << 9;
        return s[2] ^= s[0], s[3] ^= s[1], s[1] ^= s[2], s[0] ^= s[3], s[2] ^= t, s[3] = rotl(s[3], 11), result;
    }
    void discard(const usize rep)
    {
        for (usize i = 0; i < rep; i++) { (*this)(); }
    }
};
class xoshiro_64
{
private:
    using result_type = uint64_t;
    result_type s[4];
    static result_type rotl(const result_type x, const int k) { return (x << k) | (x >> (64 - k)); }

public:
    xoshiro_64() : xoshiro_64(std::random_device{}()) {}
    xoshiro_64(uint64_t seed)
    {
        uint64_t z = 0;
        for (int i = 0; i < 4; i++) { z = (seed += 0x9e3779b97f4a7c15), z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9, z = (z ^ (z >> 27)) * 0x94d049bb133111eb, s[i] = static_cast<result_type>(z ^ (z >> 31)); }
    }
    result_type operator()()
    {
        const result_type result = rotl(s[1] * 5, 7) * 9, t = s[1] << 17;
        return s[2] ^= s[0], s[3] ^= s[1], s[1] ^= s[2], s[0] ^= s[3], s[2] ^= t, s[3] = rotl(s[3], 45), result;
    }
    void discard(const usize rep)
    {
        for (usize i = 0; i < rep; i++) { (*this)(); }
    }
};
template<typename UnsignedInt, typename Rng>
class rng_base
{
public:
    using result_type = UnsignedInt;
    using rng_type    = Rng;
    static_assert(std::is_unsigned<UnsignedInt>::value, "UnsignedInt should be unsigned.");
    rng_base() : rng_base(std::random_device{}()) {}
    rng_base(const u64 seed) : rng(seed) {}
    ~rng_base() = default;
    UnsignedInt operator()() { return rng(); }
    template<typename Int>
    Int uniform_int(const Int max)
    {
        static_assert(std::is_integral<Int>::value, "Integer type is needed.");
        if (ispow2(max + 1)) { return static_cast<Int>(rng() & max); }
        const UnsignedInt mask = static_cast<UnsignedInt>(ceil2(static_cast<u64>(max + 1))) - 1;
        while (true) {
            const Int ans = static_cast<Int>(rng() & mask);
            if (ans <= max) { return ans; }
        }
    }
    template<typename Int> Int uniform_int(const Int min, const Int max) { return min + uniform_int(static_cast<Int>(max - min)); }
    bool uniform_bool() { return uniform_int<bool>(0, 1); }
    template<typename Real>
    Real uniform_real()
    {
        static_assert(std::is_floating_point<Real>::value, "FloatingPoint type is needed.");
        return static_cast<Real>(uniformInt(~static_cast<UnsignedInt>(0)) / static_cast<Real>(~static_cast<UnsignedInt>(0)));
    }
    template<typename Real> Real uniform_real(const Real min, const Real max) { return assert(min <= max), uniform_real<Real>() * (max - min) + min; }
    template<typename Int> std::pair<Int, Int> uniform_int_pair(const Int min, const Int max) { return std::minmax(uniform_int(min, max), uniform_int(min, max)); }
    template<typename Int>
    std::vector<Int> uniform_int_vec(const std::size_t size, const Int min, const Int max)
    {
        std::vector<Int> v(size);
        for (std::size_t i = 0; i < size; i++) { v[i] = uniformInt(min, max); }
        return v;
    }
    template<typename Real>
    std::vector<Real> uniform_real_vec(const std::size_t size, const Real min, const Real max)
    {
        std::vector<Real> v(size);
        for (std::size_t i = 0; i < size; i++) { v[i] = uniformReal(min, max); }
        return v;
    }
    void discard(const usize rep) { rng.discard(rep); }

private:
    Rng rng;
};
using rng_mt        = rng_base<u32, std::mt19937>;
using rng_mt64      = rng_base<u64, std::mt19937_64>;
using rng_xoshiro   = rng_base<u32, xoshiro>;
using rng_xoshiro64 = rng_base<u64, xoshiro_64>;
rng_mt g_rng_mt;
rng_mt64 g_rng_mt64;
rng_xoshiro g_rng_xo;
rng_xoshiro64 g_rng_xo64;
template<typename T>
T read()
{
    T v;
    return std::cin >> v, v;
}
template<typename T>
std::vector<T> read_vec(const std::size_t size)
{
    std::vector<T> v(size);
    for (auto& e : v) { std::cin >> e; }
    return v;
}
#define SHOW(...) static_cast<void>(0)
template<typename T>
std::vector<T> make_v(const std::size_t size, T v) { return std::vector<T>(size, v); }
template<class... Args>
auto make_v(const std::size_t size, Args... args) { return std::vector<decltype(make_v(args...))>(size, make_v(args...)); }

template<typename Cost>
class base_graph
{
public:
    using cost_type = Cost;
    base_graph(const usize sz) : sz{sz}, edges(sz), rev_edges(sz) {}
    void add_edge(const usize from, const usize to, const Cost cost, const bool bi = false)
    {
        assert(from < sz), assert(to < sz);
        edges[from].push_back(edge{from, to, cost}), rev_edges[to].push_back(edge(to, from, cost));
        if (bi) { add_edge(to, from, cost, false); }
    }
    struct edge
    {
        edge(const usize from, const usize to, const Cost cost) : from{from}, to{to}, cost{cost} {}
        const usize from, to;
        const Cost cost;
        bool operator<(const edge& e) const { return cost != e.cost ? cost < e.cost : to < e.to; }
    };
    const std::vector<edge>& operator[](const usize i) const { return assert(i < sz), edges[i]; }
    std::vector<edge>& operator[](const usize i) { return assert(i < sz), edges[i]; }
    const std::vector<std::vector<edge>>& rev_edge() const { return rev_edges; }
    std::vector<std::vector<edge>>& rev_edge() { return rev_edges; }
    friend std::ostream& operator<<(std::ostream& os, const base_graph& g)
    {
        os << "[\n";
        for (usize i = 0; i < g.V; i++) {
            for (const auto& e : g.edges[i]) { os << i << "->" << e.to << ":" << e.cost << "\n"; }
        }
        return (os << "]\n");
    }
    static usize to(const edge& e) { return e.to; }
    usize size() const { return sz; }

private:
    const usize sz;
    std::vector<std::vector<edge>> edges, rev_edges;
};
template<>
class base_graph<void>
{
public:
    base_graph(const usize sz) : sz{sz}, edges(sz), rev_edges(sz) {}
    void add_edge(const usize from, const usize to, const bool bi = false)
    {
        assert(from < sz), assert(to < sz);
        edges[from].push_back(to), rev_edges[to].push_back(from);
        if (bi) { add_edge(to, from, false); }
    }
    const std::vector<usize>& operator[](const usize i) const { return assert(i < sz), edges[i]; }
    std::vector<usize>& operator[](const usize i) { return assert(i < sz), edges[i]; }
    const std::vector<std::vector<usize>>& rev_edge() const { return rev_edges; }
    std::vector<std::vector<usize>>& rev_edge() { return rev_edges; }
    friend std::ostream& operator<<(std::ostream& os, const base_graph& g)
    {
        os << "[\n";
        for (usize i = 0; i < g.sz; i++) {
            for (const usize to : g.edges[i]) { os << i << "->" << to << "\n"; }
        }
        return (os << "]\n");
    }
    static usize to(const usize e) { return e; }
    usize size() const { return sz; }

private:
    const usize sz;
    std::vector<std::vector<usize>> edges, rev_edges;
};
using graph = base_graph<void>;
using tree  = graph;
template<typename Cost>
using cost_graph = base_graph<Cost>;
template<typename Cost>
using cost_tree = cost_graph<Cost>;
template<typename Cost>
class centroid
{
public:
    centroid(const cost_tree<Cost>& tree) : cs(tree.size())
    {
        const std::size_t sz = tree.size();
        std::vector<std::size_t> sub(sz, 1);
        std::vector<bool> used(sz, false);
        auto size = [&,sz](auto&& self, const std::size_t s, const std::size_t p) -> std::size_t {
            sub[s] = 1;
            for (const auto& e : tree[s]) {
                const std::size_t to = base_graph<Cost>::to(e);
                if (to == p or used[to]) { continue; }
                sub[s] += self(self, to, s);
            }
            return sub[s];
        };
        auto search = [&,sz](auto&& self, const std::size_t s, const std::size_t p, const std::size_t tot) -> std::size_t {
            for (const auto& e : tree[s]) {
                const std::size_t to = base_graph<Cost>::to(e);
                if (p == to or used[to]) { continue; }
                if (sub[to] * 2 > tot) { return self(self, to, s, tot); }
            }
            return s;
        };
        auto build = [&,sz](auto&& self, const std::size_t s, const std::size_t pc) -> std::size_t {
            const std::size_t tot = size(size, s, sz), c = search(search, s, sz, tot);
            used[c] = true;
            if (pc != sz) { cs.add_edge(pc, c); }
            for (const auto& e : tree[c]) {
                const std::size_t to = base_graph<Cost>::to(e);
                if (not used[to]) { self(self, to, c); }
            }
            return c;
        };
        build(build, 0, sz);
    }
    const tree& centros() const { return cs; }

private:
    tree cs;
};
// clang-format on
int main()
{
    const usize n = read<usize>();
    cost_graph<ll> g(n);
    for (usize i = 0; i < n - 1; i++) {
        const usize a = read<usize>() - 1, b = read<usize>() - 1;
        const ll c = read<ll>();
        g.add_edge(a, b, c, true);
    }
    const auto cs = centroid<ll>{g}.centros();
    std::vector<usize> in(n, 0);
    for (usize i = 0; i < n; i++) {
        for (const usize to : cs[i]) { in[to]++; }
    }
    usize c = n;
    for (usize i = 0; i < n; i++) {
        if (in[i] == 0) { c = i; }
    }
    std::vector<ll> depth(n, 0LL);
    std::vector<usize> sub(n, 0);
    ll ans   = 0;
    auto dfs = [&](auto&& self, const usize s, const usize p) -> usize {
        sub[s] = 1, ans += depth[s] * 2LL;
        for (const auto& e : g[s]) {
            if (e.to == p) { continue; }
            depth[e.to] = depth[s] + e.cost, sub[s] += self(self, e.to, s);
        }
        return sub[s];
    };
    dfs(dfs, c, n);
    ll min = inf_v<ll>;
    for (const auto& e : g[c]) {
        if (n % 2 == 0 and sub[e.to] == n / 2) {
            min = depth[e.to];
            break;
        } else {
            chmin(min, depth[e.to]);
        }
    }
    std::cout << ans - min << std::endl;
    return 0;
}


Measured memory_bytes: 40304