#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
#include <math.h>
#include <set>

using namespace std;
typedef long long  ll;
#define rep(i,s,n)for(ll i=s;i<n;i++)
#define repe(i,s,n)for(ll i=s;i<=n;i++)

static const double PI = 3.1415926535897932384626433;
static const ll  INF = (ll)1 << 55;

///////////////////////////
////Prime Creator//////////
///////////////////////////
//bool Prime[100001] = {};
//void createPrime() {
//	ll n = 100001;
//	rep(i, 0, n) Prime[i] = true;
//	Prime[0] = false;
//	Prime[1] = false;
//	rep(i, 2, n) {
//		if (Prime[i]) {
//			rep(j, 2, n) {
//				if (j*i >= n)break;
//				Prime[j*i] = false;
//			}
//		}
//	}
//}
///////////////////////////
///////////////////////////

/////////////////////////
//Warshal Floyid/////////
/////////////////////////
//initialize`
//rep(i, 0, N)rep(j, 0, N) wf[i][j] = 1 << 29;
//static const ll WF_MAX = 300;
//ll wf[WF_MAX][WF_MAX];
//void WarshalFloyid(int size) {
//	rep(k, 0, size)rep(i, 0, size)rep(j, 0, size)wf[i][j] = min(wf[i][j], wf[i][k] + wf[k][j]);
//}

////////////
///dijkstra
///////////
//ll N;
//static const ll MAX = 100001;
//static const ll INFTY = (ll)1 << 55;
//static const int WHITE = 1;
//static const int GRAY = 2;
//static const int BLACK = 3;
//vector<pair<int, int>>adj[MAX];
//ll d[MAX];
//ll pre[MAX];
//
//priority_queue<pair<int, int>>PQ;
//int color[MAX];
//ll n;
//void dijkstra(ll x) {
//	repe(i, 1, n) {
//		d[i] = INFTY;
//		color[i] = WHITE;
//	}
//
//	d[x] = 0;
//	PQ.push(make_pair(x, x));
//	color[x] = GRAY;
//	while (!PQ.empty()) {
//		pair<ll, ll> f = PQ.top(); PQ.pop();
//		ll u = f.second;
//		color[u] = BLACK;
//
//		if (d[u] < f.first * (-1))continue;
//
//		rep(j, 0, adj[u].size()) {
//			ll v = adj[u][j].first;
//			if (color[v] == BLACK)continue;
//			if (d[v] > d[u] + adj[u][j].second) {
//				d[v] = d[u] + adj[u][j].second;
//				pre[v] = u;
//				PQ.push(make_pair(d[v] * (-1), v));
//
//				color[v] = GRAY;
//			}
//		}
//	}
//}
//vector<ll> get_path(ll t) {
//	vector<ll> path;
//	for (; t != -1; t = pre[t])path.push_back(t);
//	reverse(path.begin(), path.end());
//	return path;
//}

//Belmonford
// 隣接リストで使う辺を表す型

struct Edge {
	ll to, cost;  // 辺の接続先頂点, 辺の重み
	Edge(int to, int cost) : to(to), cost(cost) {}  // コンストラクタ
};

typedef vector<vector<Edge>> AdjList;  // 隣接リストの型

AdjList graph;  // グラフの辺を格納した構造体
				// graph[v][i]は頂点vから出るi番目の辺Edge

vector<ll> dist; // 最短距離
				  // 戻り値がtrueなら負の閉路を含む
bool bellman_ford(ll n, ll s) { // nは頂点数、sは開始頂点
	dist = vector<ll>(n, INF);
	dist[s] = 0; // 開始点の距離は0
	for (int i = 0; i < n; i++) {
		for (int v = 0; v < n; v++) {
			for (int k = 0; k < graph[v].size(); k++) {
				Edge e = graph[v][k];
				if (dist[v] != INF && dist[e.to] > dist[v] + e.cost) {
					dist[e.to] = dist[v] + e.cost;
					//	cout << "update" << endl;
					if (i == n - 1) {
						//cout << "inf" << endl;
						return true;
						//return true; // n回目にも更新があるなら負の閉路が存在
					}
				}
			}
		}
	}
	return false;
}

int main() {
	int n, m, r;
	cin >> n >> m;

	ll a[2000] = {};
	ll b[2000] = {};
	ll c[2000] = {};

	graph = AdjList(n);

	rep(i, 0, m) {
		ll from, to, cost;
		cin >> from >> to >> cost;
		a[i] = from - 1;
		b[i] = to - 1;
		c[i] = -cost;
		graph[from - 1].push_back(Edge(to - 1, -cost));
	}

	if (!bellman_ford(n, 0)) {
		cout << -dist[n - 1] << endl;
		return 0;
	}
	else {
		bool negative[2000] = {};

		rep(l, 0, n) {
			rep(i, 0, n) {
				if (dist[a[i]] == INF)continue;

				if (dist[b[i]] > dist[a[i]] + c[i]) {
					dist[b[i]] = dist[a[i]] + c[i];
					negative[b[i]] = true;
				}

				if (negative[a[i]]) {
					negative[b[i]] = true;
				}
			}
		}
		if (negative[n - 1]) {
			cout << "inf" << endl;
		}
		else {
			cout << -dist[n - 1] << endl;
		}
	}

	return 0;
}

Measured memory_bytes: 384