#include <iostream> // cin, cout, cerr
#include <algorithm> // minmax, sort, swap
#include <numeric> // iota
#include <cstdio> // printf, scanf
#include <string> // string, stoi, to_string
#include <vector> // vector
#include <queue> // queue, priority_queue
#include <deque> // deque
#include <map> // key-value pairs sorted by keys
#include <set> // set
#include <iomanip> // cout<<setprecision(n)
#include <functional> // function<void(int)>
#include <cmath>
#include <cassert>
#include <bitset>

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

#define int long long // at least int64 > 9*10^18
#define EL '\n'
#define rep(i,n) for(int i = 0; i < (n); i++)
#define print(i) std::cout << (i) << '\n'
#define all(v) (v).begin(), (v).end()
/* libraries */

template <typename G>
struct rSegmentTree
{
	const int n;
	const G I;
	const std::function<G(G,G)> f, g;
	std::vector<G> data;
	rSegmentTree(int n, G I, std::function<G(G,G)> f, std::function<G(G,G)> g) : n(n), data(2*n,I), I(I), f(f), g(g) {}
	void set(int i, const G& v) {
		data[n+i] = v;
	}
	void update(int l, int r, const G& v) {
		l+=n; r+=n;
		while(r>l) {
			if(l&1) {
				if(l>=n) data[l] = f(data[l], v);
				else data[l] = g(data[l], v);
				l++;
			}
			if(r&1) {
				r--;
				if(r>=n) data[r] = f(data[r], v);
				else data[r] = g(data[r], v);
			}
			l>>=1; r>>=1;
		}
	}
	G get(int i) {
		G v = I;
		for(i+=n;i>0;i>>=1) v = f(v,data[i]);
		return v;
	}
};


struct HLD
{
	using Graph = std::vector<std::vector<int> >;
	std::vector<int> sz, in, out, par, nxt;
	Graph g, u_g;
	HLD(int n, Graph& u_g, int root=0) : sz(n),in(n),out(n),par(n),nxt(n),u_g(u_g),g(n,std::vector<int>()) {
		dfs_tree(root);
		dfs_sz(root);
		dfs_hld(root);
	}
	void dfs_tree(int v,int p=-1) {
		par[v]=p;
		for(int to:u_g[v]) {
			if(to==p) continue;
			g[v].emplace_back(to);
			dfs_tree(to,v);
		}
	}
	void dfs_sz(int v) {
		sz[v]=1;
		for(int& to:g[v]) {
			dfs_sz(to);
			sz[v]+=sz[to];
			if(sz[to]>sz[g[v][0]]) std::swap(to,g[v][0]);
		}
	}
	int t=0;
	void dfs_hld(int v) {
		in[v]=t++;
		for(int to:g[v]) {
			nxt[to] = (to==g[v][0]) ? nxt[v] : to;
			dfs_hld(to);
		}
		out[v]=t;
	}
	int LCA(int a, int b) {
		while(nxt[a]!=nxt[b]) {
			if(in[a]>in[b]) std::swap(a,b);
			b=par[nxt[b]];
		}
		if(in[a]>in[b]) std::swap(a,b);
		return a;
	}
};

struct Edge
{
	int a,b,c;
	Edge(int a, int b, int c) : a(a),b(b),c(c) {}
};

signed main() {
	int n;
	std::cin >> n;
	std::vector<std::vector<int> > g(n);
	std::vector<Edge> edges;
	rep(i,n-1) {
		int a,b,c;
		std::cin >> a >> b >> c;
		a--;b--;
		edges.emplace_back(a,b,c);
		g[a].emplace_back(b);
		g[b].emplace_back(a);
	}
	HLD hld(n,g);
	rSegmentTree<int> seg(n,0,[](int a, int b){return a+b;},[](int a, int b){return a+b;});
	rSegmentTree<int> seg2(n,0,[](int a, int b){return a+b;},[](int a, int b){return a+b;});
	int sum=0;
	for(auto e:edges) {
		if(hld.sz[e.a]>hld.sz[e.b]) std::swap(e.a,e.b);
		if(hld.sz[e.a]*2==n) {
			seg.update(0,n,e.c);
			sum+=e.c*2*(hld.sz[e.a]-1);
		} else if(hld.sz[e.a]*2<n) {
			seg.update(0,n,2*e.c);
			seg.update(hld.in[e.a],hld.out[e.a],-2*e.c);
			sum+=e.c*2*(hld.sz[e.a]-1);
		} else {
			seg.update(hld.in[e.a],hld.out[e.a],2*e.c);
			sum+=e.c*2*(n-hld.sz[e.a]-1);
		}
	}
	int max=0;
	std::vector<int> X;
	rep(i,n) X.emplace_back(seg.get(i));
	std::sort(all(X));
	std::reverse(all(X));
	max=(X[0]+X[1])/2;
	debug(max,sum);
	print(max+sum);
	return 0;
}


Measured memory_bytes: 31920