using System;
using System.Collections.Generic;
using System.Linq;
// Q050 木の直径 https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_5_A&lang=jp
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("4");
WillReturn.Add("0 1 2");
WillReturn.Add("1 2 1");
WillReturn.Add("1 3 3");
//5
}
else if (InputPattern == "Input2") {
WillReturn.Add("4");
WillReturn.Add("0 1 1");
WillReturn.Add("1 2 2");
WillReturn.Add("2 3 4");
//7
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
struct EdgeInfoDef
{
internal int ToNode;
internal int Cost;
}
static int mN;
static Dictionary<int, List<EdgeInfoDef>> mEdgeInfoListDict = new Dictionary<int, List<EdgeInfoDef>>();
static void Main()
{
List<string> InputList = GetInputList();
int[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(X => int.Parse(X)).ToArray();
mN = int.Parse(InputList[0]);
foreach (string EachStr in InputList.Skip(1)) {
SplitAct(EachStr);
int S = wkArr[0];
int T = wkArr[1];
int W = wkArr[2];
if (mEdgeInfoListDict.ContainsKey(S) == false) {
mEdgeInfoListDict[S] = new List<EdgeInfoDef>();
}
if (mEdgeInfoListDict.ContainsKey(T) == false) {
mEdgeInfoListDict[T] = new List<EdgeInfoDef>();
}
mEdgeInfoListDict[S].Add(new EdgeInfoDef { ToNode = T, Cost = W });
mEdgeInfoListDict[T].Add(new EdgeInfoDef { ToNode = S, Cost = W });
}
int wkLeafNode, wkMaxSumCost;
ExecDFS(0, out wkLeafNode, out wkMaxSumCost);
ExecDFS(wkLeafNode, out wkLeafNode, out wkMaxSumCost);
Console.WriteLine(wkMaxSumCost);
}
struct JyoutaiDef
{
internal int CurrNode;
internal int SumCost;
}
// 開始ノードを引数として深さ優先探索を行い、最長の葉ノードと最大コストを求める
static void ExecDFS(int pStaNode, out int pLeafNode, out int pMaxSumCost)
{
pLeafNode = pMaxSumCost = -1;
var Stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
WillPush.CurrNode = pStaNode;
WillPush.SumCost = 0;
Stk.Push(WillPush);
var VisitedSet = new HashSet<int>();
VisitedSet.Add(pStaNode);
while (Stk.Count > 0) {
JyoutaiDef Popped = Stk.Pop();
if (pMaxSumCost < Popped.SumCost) {
pMaxSumCost = Popped.SumCost;
pLeafNode = Popped.CurrNode;
}
if (mEdgeInfoListDict.ContainsKey(Popped.CurrNode) == false)
continue;
foreach (EdgeInfoDef EachEdgeInfo in mEdgeInfoListDict[Popped.CurrNode]) {
if (VisitedSet.Add(EachEdgeInfo.ToNode) == false) {
continue;
}
WillPush.CurrNode = EachEdgeInfo.ToNode;
WillPush.SumCost = Popped.SumCost + EachEdgeInfo.Cost;
Stk.Push(WillPush);
}
}
}
}