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++14 (GCC 5.4.1) (judge verdict: Accepted)

# include <iostream>
# include <sstream>
# include <cstdio>
# include <cstdlib>
# include <algorithm>
# include <string>
# include <cstring>
# include <cmath>
# include <stack>
# include <queue>
# include <vector>
# include <list>
# include <map>
# include <set>
# include <deque>
# include <iterator>
# include <functional>
# include <bitset>
# include <climits>
# include <ctime>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define odd(x) (x&1)
typedef long long ll;
typedef long double ld;
const ll oo = /*2 * 1000 * 1000 * 1000*/0x3f3f3f3f;
const int _cnt = 1000 * 1000;
const int _p = 1000 * 1000 * 1000 + 7;
ll o(ll x) { return x%_p; }
int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
//ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
int lcm(int a, int b) { return a / gcd(a, b)*b; }
using namespace std;

void file_put() {
	freopen("filename.in", "r", stdin);
	freopen("filename.out", "w", stdout);
}

const int N = 80;

class BigNumber {

private:

	int x[N], sgn = 0;

public:

	void shrink();

	BigNumber();

	BigNumber(const int &sgn, const int len);

	BigNumber(const int &t);

	BigNumber(const BigNumber & B);

	BigNumber(const string & s);

	void print(int num = 0) const;

	void swap(BigNumber &B);

	int size() const;

	BigNumber &operator=(const BigNumber &B);

	BigNumber &operator=(const int &A);

	BigNumber &operator=(const string & A);

	friend ostream &operator<<(ostream & output, BigNumber & B);

	friend istream &operator >> (istream & input, BigNumber & B);

	BigNumber operator+() const;

	BigNumber operator-() const;

	friend int compare(const BigNumber & A, const BigNumber & B);

	friend bool operator>(const BigNumber &A, const BigNumber &B);

	friend bool operator>=(const BigNumber &A, const BigNumber &B);

	friend bool operator<(const BigNumber &A, const BigNumber &B);

	friend bool operator<=(const BigNumber &A, const BigNumber &B);

	friend bool operator==(const BigNumber &A, const BigNumber &B);

	friend bool operator!=(const BigNumber &A, const BigNumber &B);

	friend bool operator>(const BigNumber &A, const int &B);

	friend bool operator>=(const BigNumber &A, const int &B);

	friend bool operator<(const BigNumber &A, const int &B);

	friend bool operator<=(const BigNumber &A, const int &B);

	friend bool operator==(const BigNumber &A, const int &B);

	friend bool operator!=(const BigNumber &A, const int &B);

	friend bool operator>(const int &A, const BigNumber &B);

	friend bool operator>=(const int &A, const BigNumber &B);

	friend bool operator<(const int &A, const BigNumber &B);

	friend bool operator<=(const int &A, const BigNumber &B);

	friend bool operator==(const int &A, const BigNumber &B);

	friend bool operator!=(const int &A, const BigNumber &B);

	bool operator!() const;

	friend BigNumber abs(const BigNumber &B);

	friend BigNumber operator + (const BigNumber &A, const BigNumber &B);

	friend BigNumber operator - (const BigNumber &A, const BigNumber &B);

	friend BigNumber operator * (const BigNumber &A, const BigNumber &B);

	friend BigNumber operator + (const BigNumber &A, const int &B);

	friend BigNumber operator - (const BigNumber &A, const int &B);

	friend BigNumber operator * (const BigNumber &A, const int &B);

	friend BigNumber operator + (const int &A, const BigNumber &B);

	friend BigNumber operator - (const int &A, const BigNumber &B);

	friend BigNumber operator * (const int &A, const BigNumber &B);

	BigNumber& operator +=(const BigNumber &A);

	BigNumber& operator -=(const BigNumber &A);

	BigNumber& operator *=(const BigNumber &A);

	BigNumber& operator +=(const int &A);

	BigNumber& operator -=(const int &A);

	BigNumber& operator *=(const int &A);

	BigNumber& operator ++();

	BigNumber operator ++(int);

	BigNumber& operator --();

	BigNumber operator --(int);
};


void BigNumber::shrink() {
	while (x[0] && !x[x[0]]) x[0]--;
	if (!x[0]) {
		this->x[0] = 1;
		this->sgn = 0;
	}
}

BigNumber::BigNumber() {
	sgn = 0;
	memset(x, 0, sizeof(x));
	x[0] = 1;
}

BigNumber::BigNumber(const int &sgn, const int len) {
	this->sgn = sgn;
	memset(x, 0, sizeof(x));
	x[0] = len;
}

BigNumber::BigNumber(const int &t) {
	int n = t;
	if (n > 0) sgn = 1; else
		if (n < 0) sgn = -1; else
			sgn = 0;
	n = abs(n);
	memset(x, 0, sizeof(x));
	if (!n) {
		this->x[0] = 1;
		return;
	}
	while (n) {
		x[++x[0]] = n % 10;
		n /= 10;
	}
	this->shrink();
}

BigNumber::BigNumber(const BigNumber & B) {
	this->sgn = B.sgn;
	memset(this->x, 0, sizeof(this->x));
	for (int i = 0; i <= B.x[0]; i++) this->x[i] = B.x[i];
	this->shrink();
}

BigNumber::BigNumber(const string & s) {
	string st = s;
	if (st[0] == '-') {
		this->sgn = -1;
		st.erase(st.begin());
	}
	else
		this->sgn = 1;
	memset(this->x, 0, sizeof(this->x));
	for (int i = st.length() - 1; i >= 0; i--) this->x[++x[0]] = st[i] - '0';
	if (this->x[0] == 1 && this->x[1] == 0) this->sgn = 0;
	//this->shrink();
}

void BigNumber::print(int num) const {
	if (this->sgn == -1 && this->x[x[0]] != 0) printf("-");
	if (num && this->sgn == 1 && this->x[x[0]] != 0) printf("+");
	BigNumber B = *this;
	B.shrink();
	for (int i = B.x[0]; i >= 1; i--) printf("%d", B.x[i]);
}

void BigNumber::swap(BigNumber &B) {
	std::swap(*this, B);
}

int BigNumber::size() const { return this->x[0]; }

BigNumber & BigNumber ::operator=(const BigNumber &B) {
	this->sgn = B.sgn;
	memset(this->x, 0, sizeof(this->x));
	for (int i = 0; i <= B.x[0]; i++) this->x[i] = B.x[i];
	return *this;
}

BigNumber & BigNumber ::operator=(const int &A) {
	BigNumber B = A;
	this->sgn = B.sgn;
	memset(this->x, 0, sizeof(this->x));
	for (int i = 0; i <= B.x[0]; i++) this->x[i] = B.x[i];
	return *this;
}

BigNumber & BigNumber ::operator=(const string &A) {
	BigNumber B = A;
	this->sgn = B.sgn;
	memset(this->x, 0, sizeof(this->x));
	for (int i = 0; i <= B.x[0]; i++) this->x[i] = B.x[i];
	return *this;
}

ostream &operator<<(ostream & output, BigNumber & B) {
	B.shrink();
	if (B.sgn == -1) output << '-';
	for (int i = B.x[0]; i >= 1; i--) output << B.x[i];
	return output;
}

istream &operator >> (istream & input, BigNumber & B) {
	string st;
	input >> st;
	B = BigNumber(st);
	return input;
}

BigNumber BigNumber ::operator+() const {
	return *this;
}

BigNumber BigNumber ::operator-() const {
	BigNumber t = *this;
	t.sgn = -t.sgn;
	return t;
}

int compare(const BigNumber & A, const BigNumber & B) {
	if (A.sgn > B.sgn) return 1;
	if (A.sgn < B.sgn) return -1;
	if (A.x[0] > B.x[0]) return A.sgn;
	if (A.x[0] < B.x[0]) return -A.sgn;
	for (int i = A.x[0]; i >= 1; i--) {
		if (A.x[i] > B.x[i]) return A.sgn;
		if (A.x[i] < B.x[i]) return -A.sgn;
	}
	return 0;
}

bool operator>(const BigNumber &A, const BigNumber &B) {
	return compare(A, B) == 1;
}

bool operator>=(const BigNumber &A, const BigNumber &B) {
	return compare(A, B) != -1;
}

bool operator<(const BigNumber &A, const BigNumber &B) {
	return compare(A, B) == -1;
}

bool operator<=(const BigNumber &A, const BigNumber &B) {
	return compare(A, B) != 1;
}

bool operator==(const BigNumber &A, const BigNumber &B) {
	return compare(A, B) == 0;
}

bool operator!=(const BigNumber &A, const BigNumber &B) {
	return compare(A, B) != 0;
}

bool operator>(const BigNumber &A, const int &B) {
	return compare(A, B) == 1;
}

bool operator>=(const BigNumber &A, const int &B) {
	return compare(A, B) != -1;
}

bool operator<(const BigNumber &A, const int &B) {
	return compare(A, B) == -1;
}

bool operator<=(const BigNumber &A, const int &B) {
	return compare(A, B) != 1;
}

bool operator==(const BigNumber &A, const int &B) {
	return compare(A, B) == 0;
}

bool operator!=(const BigNumber &A, const int &B) {
	return compare(A, B) != 0;
}

bool operator>(const int &A, const BigNumber &B) {
	return compare(A, B) == 1;
}

bool operator>=(const int &A, const BigNumber &B) {
	return compare(A, B) != -1;
}

bool operator<(const int &A, const BigNumber &B) {
	return compare(A, B) == -1;
}

bool operator<=(const int &A, const BigNumber &B) {
	return compare(A, B) != 1;
}

bool operator==(const int &A, const BigNumber &B) {
	return compare(A, B) == 0;
}

bool operator!=(const int &A, const BigNumber &B) {
	return compare(A, B) != 0;
}

bool BigNumber ::operator!() const { return *this == 0; }

BigNumber abs(const BigNumber &B) { return (B >= 0) ? (+B) : (-B); }

BigNumber operator + (const BigNumber &A, const BigNumber &B) {
	if (!A) return B;
	if (!B) return A;
	if (A.sgn == B.sgn) {
		BigNumber C(A.sgn, max(A.x[0], B.x[0]));
		for (int i = 1; i <= C.x[0]; i++) C.x[i] = A.x[i] + B.x[i];
		for (int i = 1; i <= C.x[0]; i++) C.x[i + 1] += C.x[i] / 10, C.x[i] %= 10;
		C.x[0] += (C.x[C.x[0] + 1] > 0);
		return C;
	}
	if (A < 0) return B - (-A); else return A - (-B);
}

BigNumber operator - (const BigNumber &A, const BigNumber &B) {
	if (!A) return -B;
	if (!B) return A;
	if (A < 0) return -(-A + B);
	if (B < 0) return A + (-B);
	if (A < B) return -(B - A);
	BigNumber C(1, A.x[0]);
	for (int i = 1; i <= C.x[0]; i++) C.x[i] = A.x[i] - B.x[i];
	for (int i = 1; i <= C.x[0]; i++) {
		C.x[i + 1] -= (C.x[i] < 0);
		C.x[i] += (C.x[i] < 0) * 10;
	}
	while (C.x[0] > 1 && !C.x[C.x[0]]) C.x[0]--;
	C.sgn = !(C.x[0] == 1 && !C.x[1]);
	return C;
}

BigNumber operator * (const BigNumber &A, const BigNumber &B) {
	if (!A || !B) return 0;
	BigNumber C(A.sgn*B.sgn, A.x[0] + B.x[0] - 1);
	for (int i = 1; i <= A.x[0]; i++)
		for (int j = 1; j <= B.x[0]; j++)
			C.x[i + j - 1] += A.x[i] * B.x[j];
	for (int i = 1; i <= C.x[0]; i++) C.x[i + 1] += C.x[i] / 10, C.x[i] %= 10;
	while (C.x[C.x[0] + 1]) {
		C.x[0]++;
		C.x[C.x[0] + 1] += C.x[C.x[0]] / 10;
		C.x[C.x[0]] %= 10;
	}
	return C;
}

BigNumber operator + (const BigNumber &A, const int &B) { return A + BigNumber(B); }

BigNumber operator - (const BigNumber &A, const int &B) { return A - BigNumber(B); }

BigNumber operator * (const BigNumber &A, const int &B) { return A * BigNumber(B); }

BigNumber operator + (const int &A, const BigNumber &B) { return BigNumber(A) + B; }

BigNumber operator - (const int &A, const BigNumber &B) { return BigNumber(A) - B; }

BigNumber operator * (const int &A, const BigNumber &B) { return BigNumber(A) * B; }

BigNumber& BigNumber ::operator +=(const BigNumber &A) { return *this = *this + A; }

BigNumber& BigNumber ::operator -=(const BigNumber &A) { return *this = *this - A; }

BigNumber& BigNumber ::operator *=(const BigNumber &A) { return *this = *this * A; }

BigNumber& BigNumber ::operator +=(const int &A) { return *this = *this + A; }

BigNumber& BigNumber ::operator -=(const int &A) { return *this = *this - A; }

BigNumber& BigNumber ::operator *=(const int &A) { return *this = *this * A; }

BigNumber& BigNumber ::operator ++() { return *this += 1; }

BigNumber BigNumber ::operator ++(int) { return *this += 1; }

BigNumber& BigNumber ::operator --() { return *this -= 1; }

BigNumber BigNumber ::operator --(int) { return *this -= 1; }



const int MAXN = 200005;
const ll INF = 9223372036854775807;
struct Edge {
	int v;
	int cost;
	Edge(int _v = 0, int _cost = 0) :v(_v), cost(_cost) {}
};
vector<Edge>E[MAXN];
void addedge(int u, int v, int w) {
	E[u].push_back(Edge(v, w));
}
bool vis[MAXN];
int cnt[MAXN];
ll dist[MAXN];
bool SPFA(int start, int n) {
	memset(vis, false, sizeof(vis));
	for (int i = 1; i <= n; i++)dist[i] = INF;
	vis[start] = true;
	dist[start] = 0;
	queue<int>que;
	while (!que.empty())que.pop();
	que.push(start);
	memset(cnt, 0, sizeof(cnt));
	cnt[start] = 1;
	while (!que.empty()) {
		int u = que.front();
		que.pop();
		vis[u] = false;
		for (int i = 0; i<E[u].size(); i++) {
			int v = E[u][i].v;
			if (dist[v]>dist[u] + E[u][i].cost) {
				dist[v] = dist[u] + E[u][i].cost;
				if (!vis[v]) {
					vis[v] = true;
					if (cnt[v] > n) continue;
					cnt[v]++;
					que.push(v);
				}
			}
		}
	}
	return true;
}

int n, m, a, b, c;

struct biantype {
	int x, y, c;
};

biantype bian[200005];
int cnt_ = 0;

bool negative[2000005];

int main() {
	//file_put();

	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) {
		scanf("%d%d%d", &a, &b, &c);
		addedge(a, b, -c);
		cnt_++;
		bian[cnt_].x = a;
		bian[cnt_].y = b;
		bian[cnt_].c = -c;
	}
	SPFA(1, n);
	memset(negative, false, sizeof(negative));
	for (int j = 1; j <= n - 1; j++) {
		for (int i = 1; i <= cnt_; i++) {
			if (dist[bian[i].x] == INF) continue;
			if (dist[bian[i].y] > dist[bian[i].x] + bian[i].c) {
				dist[bian[i].y] = dist[bian[i].x] + bian[i].c;
				negative[bian[i].y] = 1;
			}
			if (negative[bian[i].x]) negative[bian[i].y] = 1;
		}
	}
	if (negative[n]) cout << "inf\n" << endl; else cout << (-dist[n]);

	return 0;
}