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;
 
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;
 
    foreach(i;1..N){
        scores[i]=new_score(i);
        update_under(i);
        if(scores[i]!=new_score(i)){
            writeln("inf");
            return;
        }
    }
    writeln(scores[N-1]);
}

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

void update_under(int roof){
    onUpdate(roof,roof);
}

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

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