#include <bits/stdc++.h>

#define REP(i,n) for (int i=0;i<(n);++i)

using namespace std;

using ll = long long;

template <class Weight>
struct edge {
    using weight_type = Weight;

    size_t to;
    Weight m_weight;

    edge(size_t to, Weight weight = 1) : to(to), m_weight(weight) {}

    Weight weight() const {
        return m_weight;
    }
};

template <class Weight>
class graph {
private:
    const bool is_directed;

public:
    using edge_type = edge<Weight>;

    const size_t count_vertices;
    vector<edge<Weight>> *edges;

    graph(size_t count_vertices, bool is_directed = true) : count_vertices(count_vertices), is_directed(is_directed) {
        edges = new vector<edge<Weight>>[count_vertices];
    }

    ~graph() {
        delete [] edges;
    }

    void make_edge(size_t u, size_t v, Weight weight) {
        edges[u].push_back(edge<Weight>(v, weight));
        if (!is_directed) {
            edges[v].push_back(edge<Weight>(u, weight));
        }
    }
};

enum value_class_type {
    finite_class,
    pos_inf_class,
    neg_inf_class
};

template <class T>
struct non_standard {
    value_class_type value_class;
    T value;

    non_standard(T value) : value_class(value_class_type::finite_class), value(value) { }

    non_standard(value_class_type value_class, T value) : value_class(value_class), value(value) { }

    bool is_finite() const {
        return value_class == value_class_type::finite_class;
    }

    bool is_pos_inf() const {
        return value_class == value_class_type::pos_inf_class;
    }

    bool is_neg_inf() const {
        return value_class == value_class_type::neg_inf_class;
    }

    static non_standard pos_inf() {
        return non_standard(value_class_type::pos_inf_class, 0);
    }

    static non_standard neg_inf() {
        return non_standard(value_class_type::neg_inf_class, 0);
    }
};


template <class Graph>
std::vector<non_standard<typename Graph::edge_type::weight_type>> bellman_ford(const Graph &g, size_t start) {
    using Edge = typename Graph::edge_type;
    using Weight = typename Edge::weight_type;

    const non_standard<Weight> POS_INF = non_standard<Weight>::pos_inf();
    const non_standard<Weight> NEG_INF = non_standard<Weight>::neg_inf();

    size_t n = g.count_vertices;
    std::vector<non_standard<Weight>> dist(n, POS_INF);
    dist[start] = non_standard<Weight>(0);
    for (size_t count_loop = 0; ; ++count_loop) {
        bool updated = false;
        for (size_t u = 0; u < n; ++u) {
            if (dist[u].is_finite()) {
                for (const Edge &e: g.edges[u]) {
                    size_t v = e.to;
                    Weight weight = e.weight();
                    if (dist[v].is_pos_inf() || dist[v].is_finite() && dist[v].value > dist[u].value + weight) {
                        if (count_loop < n) {
                            dist[v] = non_standard<Weight>(dist[u].value + weight);
                        } else {
                            dist[v] = NEG_INF;
                        }
                        updated = true;
                    }
                }
            } else if (dist[u].is_neg_inf()) {
                for (const Edge &e: g.edges[u]) {
                    size_t v = e.to;
                    if (!dist[v].is_neg_inf()) {
                        dist[v] = NEG_INF;
                        updated = true;
                    }
                }

            }
        }
        if (!updated) {
            break;
        }
    }
    return dist;
}


int main() {
    size_t N, M;
    cin >> N >> M;
    graph<ll> g(N);
    REP(_, M) {
        int a, b, c;
        cin >> a >> b >> c;
        --a; --b;
        g.make_edge(a, b, -c);
    }
    auto dist = bellman_ford(g, 0);
    if (dist[N - 1].is_finite()) {
        cout << -dist[N - 1].value << endl;
    } else if (dist[N - 1].is_neg_inf()) {
        cout << "inf" << endl;
    } else {
        assert(0);
    }

    return 0;
}

Measured memory_bytes: 384