/**************************************************************** 
 * Description: 
 * Author: Alex Li
 * Date: 2024-08-19 20:32:32
 * LastEditTime: 2024-08-19 20:32:43
****************************************************************/
#include<iostream>
using namespace std;

const int V = 100;  // 定义最大顶点数量V为100
int n, m, ans;  // n表示顶点数量，m表示边的数量，ans表示最长路径的长度
int e[V][V];  // 邻接矩阵e，用于存储边的权值，初始化为-1表示无边
bool visited[V];  // 记录每个顶点是否被访问过

// 深度优先搜索函数，用于查找从顶点x开始的最长路径
void dfs(int x, int len) 
{
    int i;
    visited[x] = true;  // 标记当前顶点x已访问
    if (len > ans)  // 如果当前路径长度len大于已记录的最长路径ans
        ans = len;  // 更新最长路径长度
    for (i = 1; i <= n; i++)  // 遍历所有顶点
        if ((!visited[i]) && (e[x][i] != -1))  // 如果顶点i未被访问过且与顶点x之间有边
            dfs(i, len + e[x][i]);  // 递归调用dfs，继续探索以顶点i为起点的路径
    visited[x] = false;  // 回溯时，将顶点x标记为未访问
}

int main() 
{
    int i, j, a, b, c;
    cin >> n >> m;  // 输入顶点数量n和边的数量m
    
    // 初始化邻接矩阵，将所有边的权值设置为-1（表示无边）
    for (i = 1; i <= n; i++)
        for (j = 1; j <= n; j++)
            e[i][j] = -1;

    // 输入每条边的信息，更新邻接矩阵
    for (i = 1; i <= m; i++) 
    {
        cin >> a >> b >> c;  // 输入边的两个顶点a、b以及边的权值c
        e[a][b] = c;  // 设置边a到b的权值为c
        e[b][a] = c;  // 设置边b到a的权值为c（无向图）
    }

    // 初始化visited数组，所有顶点初始状态均未被访问
    for (i = 1; i <= n; i++)
        visited[i] = false;

    ans = 0;  // 初始化最长路径的长度为0

    // 对每个顶点都进行一次深度优先搜索，计算最长路径
    for (i = 1; i <= n; i++)
        dfs(i, 0);

    cout << ans << endl;  // 输出最长路径的长度
    return 0;
}
