Language: C++

#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <set>
#include <queue>
using namespace std;
using int64 = long long;
using vint = vector<int>;
#define Rep(i, n) for (int i = 0; i < (n); ++i)
#define InitRep(i, init, n) for (int i = (init); i < (n); ++i)
#define RepLong(i, n) for (int64 i = 0; i < (n); ++i)
#define InitRepLong(i, init, n) for (int64 i = (init); i < (n); ++i)
#define RepItr(it, itBegin, itEnd) for (auto it = (itBegin); it != (itEnd); ++it)


void dfs(vector<set<int>> &graph, vint &preClock, vint &postClock, int vertex, int clock)
{
	++clock;
	preClock[vertex] = clock;
	for (const int child : graph[vertex])
	{
		if (preClock[child] == 0)
		{
			dfs(graph, preClock, postClock, child, clock);
		}
	}
	++clock;
	postClock[vertex] = clock;
}

bool dfsReachable(vector<set<int>> &graph, vint &seen, vint &reachable, int vertex)
{
	seen[vertex] = 1;
	for (const int child : graph[vertex])
	{
		if (seen[child]) continue;
		if (reachable[child])
		{
			reachable[vertex] = 1;
			return true;
		}
		else
		{
			if (dfsReachable(graph, seen, reachable, child))
			{
				reachable[vertex] = 1;
				return true;
			}
		}
	}
	return false;
}

int main()
{
	int n, m, p;
	cin >> n >> m >> p;
	vector<set<int>> graph(n);
	vector<vint> vertexesFrom(n);
	vector<vint> cost(n, vint(n, INT_MAX / 2));
	vint hasLoop(n);
	Rep(i, m)
	{
		int a, b, c;
		cin >> a >> b >> c;
		--a;
		--b;
		if (a == b)
		{
			if (c > p)
			{
				hasLoop[a] = 1;
			}
		}
		else
		{
			graph[a].insert(b);
			c = -(c - p);
			if (c < cost[a][b])
			{
				cost[a][b] = c;
			}
		}
	}

	vint reachable(n);
	reachable[0] = 1;
	reachable[n - 1] = 1;
	vint preClock(n), postClock(n);
	dfs(graph, preClock, postClock, 0, 0);
	Rep(i, n)
	{
		// 頂点1から辿ることのできない頂点と、そこへ向かう辺を削除
		if (preClock[i] == 0)
		{
			graph[i].clear();
			for (const int from : vertexesFrom[i])
			{
				graph[from].erase(i);
				cost[from][i] = INT_MAX / 2;
			}
		}
		// 頂点nの先祖になっている頂点をreachableとする
		if (preClock[i] < preClock[n - 1] && postClock[i] > postClock[n - 1])
		{
			reachable[i] = 1;
		}
	}
	
	// まだreachableになっていない頂点に対して、その頂点を起点とするDFS
	Rep(i, n)
	{
		if (reachable[i]) continue;
		vint seen(n);
		dfsReachable(graph, seen, reachable, i);
	}

	// ここでreachableになっていないものは頂点nへ到達できないので、その頂点とそこへ向かう辺を削除
	// 逆にreachableで意味のある自己loopを持つ頂点がある場合、最大値なし
	Rep(i, n)
	{
		if (!reachable[i])
		{
			for (const int from : vertexesFrom[i])
			{
				graph[from].erase(i);
				cost[from][i] = INT_MAX / 2;
			}
		}
		else if (hasLoop[i])
		{
			cout << -1 << endl;
			return 0;
		}
	}

	// ベルマンフォード法
	vint distance(n, INT_MAX / 2);
	distance[0] = 0;
	queue<int> que;
	que.push(0);
	int bfCount = 0;
	while (!que.empty())
	{
		int parent = que.front();
		que.pop();
		for (const int child : graph[parent])
		{
			int newDistance = distance[parent] + cost[parent][child];
			if (newDistance < distance[child])
			{
				distance[child] = newDistance;
				que.push(child);
			}
		}
		++bfCount;
		if (bfCount > n)
		{
			// 負閉路が存在
			cout << -1 << endl;
			return 0;
		}
	}
	int answer = -distance[n - 1];
	cout << (answer > 0 ? answer : 0) << endl;

	return 0;
}

Compiler output:
a.cc: In function 'int main()':
a.cc:63:38: error: 'INT_MAX' was not declared in this scope
   63 |         vector<vint> cost(n, vint(n, INT_MAX / 2));
      |                                      ^~~~~~~
a.cc:9:1: note: 'INT_MAX' is defined in header '<climits>'; this is probably fixable by adding '#include <climits>'
    8 | #include <queue>
  +++ |+#include <climits>
    9 | using namespace std;