import std.stdio, std.string, std.array, std.conv, std.algorithm, std.typecons, std.range, std.container, std.math, std.algorithm.searching, std.functional,std.mathspecial, std.numeric;

long[] scores;
int[][] abcs;

int[] reachTo;
int[] reachFrom;

void main(){
    auto nm=readln.split.map!(to!int).array;
    auto N=nm[0];
    auto M=nm[1];
    foreach(i;0..M){
        auto abc=readln.split.map!(to!int).array;
        abc[0]-=1;
        abc[1]-=1;
        abcs~=abc;
    }

    scores.length=N;
    foreach(ref s;scores[1..$])s=long.min;

    addReachTo(N-1);
    addReachFrom(0);

    foreach(i,r;reachFrom){
        if(i==0)continue;
        scores[r]=new_score(r,reachFrom[0..i]);
        onUpdate(reachFrom[0..i], r);
        if(scores[i]!=new_score(i,reachFrom[0..i])){
            writeln("inf");
            return;
        }
    }
    writeln(scores[N-1]);
}

long new_score(int target, int[] froms){
    auto edges=abcs.filter!(abc=>!froms.find(abc[0]).empty && abc[1]==target);
    auto res=(edges.map!(abc=>scores[abc[0]]+abc[2]));
    return (long.min).reduce!max(res);
}

void update(int[] froms, int[] abc){
    auto res=scores[abc[0]]+abc[1];
    if(scores[abc[1]]>=res)return;
    scores[abc[1]]=res;
    onUpdate(froms, abc[1]);
}

void onUpdate(int[] froms, int current){
    auto edges=abcs.filter!(edge=>edge[0]==current && !froms.find(edge[1]).empty);
    foreach(edge;edges){
        update(froms,edge);
    }
}

void addReachTo(int to){
    if(reachTo.find(to).empty){
        reachTo~=to;
        auto edges=abcs.filter!(edge=>edge[1]==to);
        foreach(e;edges)addReachTo(e[0]);
    }
}

void addReachFrom(int from){
    if(!reachTo.find(from).empty && reachFrom.find(from).empty){
        reachFrom~=from;
        auto edges=abcs.filter!(edge=>edge[0]==from);
        foreach(e;edges)addReachFrom(e[1]);
    }
}
