Problem:
Score : 400 points

Problem Statement

There is a directed graph with N vertices and M edges.
The i-th edge (1≤i≤M) points from vertex a_i to vertex b_i, and has a weight c_i.
We will play the following single-player game using this graph and a piece.

Initially, the piece is placed at vertex 1, and the score of the player is set to 0.
The player can move the piece as follows:

When the piece is placed at vertex a_i, move the piece along the i-th edge to vertex b_i. After this move, the score of the player is increased by c_i.

The player can end the game only when the piece is placed at vertex N.
The given graph guarantees that it is possible to traverse from vertex 1 to vertex N.

When the player acts optimally to maximize the score at the end of the game, what will the score be?
If it is possible to increase the score indefinitely, print inf.

Constraints

2≤N≤1000

1≤M≤min(N(N-1),2000)

1≤a_i,b_i≤N (1≤i≤M)

a_i≠b_i (1≤i≤M)

a_i≠a_j or b_i≠b_j (1≤i<j≤M)

-10^9≤c_i≤10^9 (1≤i≤M)

c_i is an integer.

In the given graph, there exists a path from vertex 1 to vertex N.

Input

Input is given from Standard Input in the following format:

N M
a_1 b_1 c_1
a_2 b_2 c_2
:
a_M b_M c_M

Output

Print the maximum possible score at the end of the game, if it is finite. If it is possible to increase the score indefinitely, print inf.

Sample Input 1

3 3
1 2 4
2 3 3
1 3 5

Sample Output 1

7

There are two ways to move the piece to vertex N=3:

vertex 1 → vertex 2 → vertex 3 : score 4+3=7

vertex 1 → vertex 3 : score 5

Thus, the maximum possible score at the end of the game is 7.

Sample Input 2

2 2
1 2 1
2 1 1

Sample Output 2

inf

It is possible to increase the score indefinitely by alternating between vertex 1 and 2.

Sample Input 3

6 5
1 2 -1000000000
2 3 -1000000000
3 4 -1000000000
4 5 -1000000000
5 6 -1000000000

Sample Output 3

-5000000000

Solution in C# (Mono-mcs 6.8.0.105) (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Threading.Tasks;

/*
・概要
Bellman-Ford法は、
重み付き有向グラフにおける単一始点の最短経路問題を解くアルゴリズム。
辺の重みに負数が存在する場合に主に使う。
（cf. 辺の重みが非負数ならば、ダイクストラ法の方が高速）

・使用法
	1. BellmanFordクラスのインスタンスを作成
	引数は、頂点数N
	（e.g. BellmanFord graph = new BellmanFord(N);）

	2. 与えられた辺を追加
	引数は、始点、終点、重み
	（e.g. graph.AddEdge(start,goal,value);）

	3. BellmanFord法で最短距離を決定する
	負の閉路で無限ループし、最短距離が求まらない場合は、falseを返す
	（e.g. bool found = graph.SetDist();）

	4. （最短経路が見つかった場合）始点からの最短距離を取得する
	引数は、目的地のインデックス
	（e.g. long ans = graph.GetDist(N-1);）

・アルゴリズム（計算量は O (V * E)：Vは頂点の数、Eは辺の数）
ループを回して、各ノードへの最短距離を更新し続ける。

・詳細

*/

class Program
{
	//Main
	static void Main(string[] args)
	{
		//読み込む
		string[] S = Console.ReadLine().Split(' ');
		int N = int.Parse(S[0]);
		int M = int.Parse(S[1]);

		//1. BellmanFordクラスのインスタンスを作成
		//引数は、頂点数N
		BellmanFord graph = new BellmanFord(N);

		//2. 与えられた辺を追加
		for(int i=0; i<M; i++){
				string[] line = Console.ReadLine().Split(' ');
				int a = int.Parse(line[0])-1;
				int b = int.Parse(line[1])-1;
				//この問題では最長距離を求めるので、重みの正負を逆転させる
				long c = long.Parse(line[2]) * -1;

				//辺を追加
				/*
				引数は、始点、終点、重み
				*/
				graph.AddEdge(a,b,c);
		}

		//3. BellmanFord法で最短距離を決定する
		/*
		負の閉路で無限ループし、最短距離が求まらない場合は、falseを返す
		*/
		bool found = graph.SetDist();

		//出力
		//見つかった場合
		if(found){
			//4. 始点からの最短距離を取得する
			//引数は、目的地のインデックス
			long ans = graph.GetDist(N-1);

			//この問題では正負を逆転したので、元に戻す
			ans = -1 * ans;
			Console.WriteLine(ans);
		}
		//見つからなかった場合
		else{
			Console.WriteLine("inf");
		}
	}
}


//Bellman-Ford法を用いて、最短距離を求める為のクラス
class BellmanFord{
	//最短距離の初期化に使う変数
	/*
	大き過ぎると、オーバーフローして大小比較にバグが生じるので注意！！！！
	*/
	static readonly long inf = 1000000000000;

	//辺を保存する構造体
	public struct Edge
	{
		//始点
		public int Start;
		//終点
		public int Goal;
		//重み（負数もOK）
		public long Value;

		public Edge(int s, int g, long v){
			this.Start = s;
			this.Goal = g;
			this.Value = v;
		}
	}

	//辺を保存するリスト
	List<Edge> edgeList;
	//各頂点への最短距離を保存する配列
	long[] minDist;

	//コンストラクタ
	/*
	引数は頂点数
	*/
	public BellmanFord(int vertex){
		this.edgeList = new List<Edge>();

		//各頂点への最短距離をinfで初期化
		//但し、当然、インデックス0（始点から始点）は除く
		this.minDist = new long[vertex];
		for(int i=1; i<vertex; i++){
			minDist[i] = inf;
		}
	}

	//辺を追加するメソッド
	/*
	引数は、始点、終点、重み
	*/
	public void AddEdge(int start, int goal, long value){
		Edge edge = new Edge(start, goal, value);
		this.edgeList.Add(edge);
	}

	//Bellman-Ford法で、最短距離を求めるメソッド
	/*
	最短距離が求まる場合はtrueを、求まらない場合はfalseを返す
	*/
	public bool SetDist(){
		//最短距離が求まるかのbool
		bool found = true;

		//頂点数と辺数
		int V = this.minDist.Length;
		int E = this.edgeList.Count();

		//ループで最小値を更新
		//各ノードへの到達最小値を更新し続ける
		for(int i=0; i<V; i++){
			for(int j=0; j<E; j++){
				//当該頂点の始点、終点、重み
				int start = edgeList[j].Start;
				int goal = edgeList[j].Goal;
				long value = edgeList[j].Value;

				//最小値を更新できる場合（この辺を使った方が重みが少ない場合）
				if(this.minDist[goal] > this.minDist[start] + value){
					this.minDist[goal] = this.minDist[start] + value;

					//頂点の数と同じ回数ループしている場合、無限ループになる
					//負の閉路があることを検知（マイナスの経路を延々とループ）
					if(i == V-1){
							found = false;
					}
				}
			}
		}

		//見つかったかどうかを出力
		return found;
	}

	//始点からの最短距離を出力
	public long GetDist(int goal){
		return this.minDist[goal];
	}
}