//include
//------------------------------------------
#include <string>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>

#include <numeric>
#include <utility>
#include <complex>

#include <sstream>
#include <iostream>
#include <iomanip>

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <ctime>

// namespace
using namespace std;

// type alias
using ll = long long;
using ull = unsigned long long;
using comp = complex<double>;

// constant
static const ll MOD = 998244353LL;
static const double PI = 3.14159265358979323846;

// conversion
inline ll toint(string s) { ll v; istringstream sin(s); sin >> v; return v; }
template<class t> inline string tostring(t x) { ostringstream sout; sout << x; return sout.str(); }

// print
#define RET(x) return cout << x << endl, 0;

// for loop
#define REP(i, a, b) for ((i) = (ll)(a);(i) < (ll)(b);(i)++)
#define REPD(i, a, b) for (ll i = (ll)(a);(i) < (ll)(b);(i)++)
#define REPI(v, vs) for (auto& v : vs)

//debug
#ifdef LOCAL_ENV
#define DUMP(x)  cerr << #x << " = " << (x) << endl
#define DEBUG(x) cerr << #x << " = " << (x) << " (l" << __LINE__ << ")" << " " << __FILE__ << endl
#else
#define DUMP(x)
#define DEBUG(x)
#endif

#define MAX_VALUE 9223372036854775807LL

template <ull N, class T, class... Args, std::enable_if_t<N == 0, int> = 0>
auto make_multiple_vector(Args... args) {
    return T(args...);
}

template <ull N, class T, class... Args, std::enable_if_t<N != 0, int> = 0>
auto make_multiple_vector(ull size, Args... args) {
    using value_type = std::decay_t<decltype(make_multiple_vector<N - 1, T>(args...))>;
    return vector<value_type>(size, make_multiple_vector<N - 1, T>(args...));
}



template <class EdgeInfo>
struct Graph {
	using Vertex = ll;
	using Edge = tuple<Vertex, Vertex, EdgeInfo>;
	ll vertex_count;
	vector<Edge> edges;

	Graph() : vertex_count(0LL), edges(0LL) {}
	Graph(ll vertex_count) : vertex_count(vertex_count), edges(0LL) {}

	void add_edge(Vertex from, Vertex to, EdgeInfo edge_info)
	{
		edges.emplace_back(from, to, edge_info);
	}

	void add_edge(Vertex from, Vertex to)
	{
		edges.emplace_back(from, to, EdgeInfo());
	}

	vector<vector<Edge>> get_adjacency_list() const
	{
		// 辺の隣接リストを作成
		vector<vector<Edge>> adjancency_list(vertex_count);
		for (ll i = 0; i < edges.size(); ++i)
		{
			Vertex from, to;
			EdgeInfo info;
			tie(from, to, info) = edges[i];
			adjancency_list[from].emplace_back(from, to, info);
		}
		return move(adjancency_list);
	}

	vector<vector<Vertex>> get_adjacency_list_with_no_info() const
	{
		// 辺の隣接リストを作成
		vector<vector<Vertex>> adjancency_list(vertex_count);
		for (ll i = 0; i < edges.size(); ++i)
		{
			Vertex from, to;
			EdgeInfo info;
			tie(from, to, info) = edges[i];
			adjancency_list[from].emplace_back(to);
		}
		return move(adjancency_list);
	}
};

pair<vector<ll>, vector<ll>> dijkstra(const Graph<ll>& graph, ll s = 0LL)
{
	using Vertex = ll;
	using Length = ll;

	// 辺の隣接リストを作成
	auto adjacency_list = graph.get_adjacency_list();

	// アルゴリズム本体
	using VertexInfo = pair<Length, Vertex>;
	priority_queue<VertexInfo, vector<VertexInfo>, greater<VertexInfo>> queue;
	vector<Length> dists(graph.vertex_count, 1LL << 60);
	vector<Vertex> prev_vertices(graph.vertex_count, -1LL);

	dists[s] = 0LL;
	queue.emplace(dists[s], s);
	prev_vertices[s] = s;
	Vertex v, from, to;
	Length l, length;
	while (!queue.empty())
	{
		tie(l, v) = queue.top();
		queue.pop();
		if (dists[v] < l) continue;
		for (auto& edge : adjacency_list[v])
		{
			tie(from, to, length) = edge;
			if (dists[to] > dists[v] + length)
			{
				dists[to] = dists[v] + length;
				queue.emplace(dists[to], to);
				prev_vertices[to] = v;
			}
		}
	}
	for (ll i = 0; i < graph.vertex_count; ++i)
	{
		if (prev_vertices[i] == -1LL)
			dists[i] = -1LL;
	}

	return { dists, prev_vertices };
}

// 始点 s から各点への最短距離を返します。
// パス自体が存在しない場合は -1 を返します。
// 距離 lengths の各要素にとくに条件はありません。
// 長さが負となる経路が存在しない場合を想定しており、負経路が存在するかは別の方法で検出する必要があります。
pair<vector<ll>, vector<ll>> bellman_ford(const Graph<ll>& graph, ll s, ll iter_count)
{
	using Vertex = ll;
	using Length = ll;

	// アルゴリズム本体
	vector<Length> dists(graph.vertex_count, 1LL << 60);
	vector<Vertex> prev_vertices(graph.vertex_count, -1LL);

	dists[s] = 0LL;
	prev_vertices[s] = s;
	ll from, to, length;
	for (ll i = 0; i + 1 < iter_count; ++i)
	{
		for (ll j = 0; j < graph.edges.size(); ++j)
		{
			auto& edge = graph.edges[j];
			tie(from, to, length) = edge;
			if (dists[to] > dists[from] + length)
			{
				dists[to] = min(dists[to], dists[from] + length);
				prev_vertices[to] = from;
			}
		}
	}

	return { dists, prev_vertices };
}

pair<vector<ll>, vector<ll>> bellman_ford(const Graph<ll>& graph, ll s = 0LL)
{
	return bellman_ford(graph, s, graph.vertex_count);
}

int solve() {
	ll N, M, P;
	cin >> N >> M >> P;
	vector<tuple<ll, ll, ll>> edges;
	ll a, b, c;
	Graph<ll> g_from_1(N);
	Graph<ll> g_to_N(N);
    REPD(i, 0, M) {
		cin >> a >> b >> c;
		--a, --b;
		g_from_1.add_edge(a, b, 1);
		g_to_N.add_edge(b, a, 1);
		edges.emplace_back(a, b, c);
	}

	auto dist_from_1 = dijkstra(g_from_1).first;
	auto dist_to_N = dijkstra(g_to_N, N - 1).first;
	vector<bool> can_reach(N);
	REPD(i, 0, N) {
		can_reach[i] = dist_from_1[i] >= 0 && dist_to_N[i] >= 0;
	} 

    Graph<ll> g(N);
    REPD(i, 0, M) {
		tie(a, b, c) = edges[i];
		if (can_reach[a] && can_reach[b]) g.add_edge(a, b, P - c);
	}
	auto dists = bellman_ford(g).first;
	auto dists2 = bellman_ford(g, 0, g.edges.size() * 4LL).first;

	bool has_neg_loop = false;
	for (ll i = 0; i < N; ++i) if (can_reach[i] && dists[i] != dists2[i]){
			has_neg_loop = true;
			break;
	}

	if (has_neg_loop) RET(-1);
	RET((-dists[N - 1] >= 0 ? -dists[N - 1]: 0LL));

	return 0;
}

//main function
int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);

	solve();
	// ll t;
	// cin >> t;
	// REPD(i, 0, t) solve();

	return 0;
}


Measured memory_bytes: 4244