#include <bits/stdc++.h>
using namespace std;

struct Dummyf { template <typename... Ts> void operator()(Ts&&...) {} };

template <typename T> T load() { T r; cin >> r; return r; }
template <typename T> vector<T> loadMany(int n) { vector<T> rs(n); generate(rs.begin(), rs.end(), &load<T>); return rs; }

struct Graph {
	template <typename Pre=Dummyf, typename Post=Dummyf, typename PreE=Dummyf, typename PostE=Dummyf, typename FailE=Dummyf> void DFS(int source, Pre pre, Post post, PreE pree, PostE poste, FailE faile) const {
		auto visit = vector<bool>(size(), false);
		implDFS(source, visit, pre, post, pree, poste, faile);
	}
	template <typename Pre=Dummyf, typename Post=Dummyf, typename PreE=Dummyf, typename PostE=Dummyf, typename FailE=Dummyf> void implDFS(int v, vector<bool>& visit, Pre pre, Post post, PreE pree, PostE poste, FailE faile) const {
		visit[v] = true;
		pre(v);
		for (auto u : edges[v])
			if (not visit[u])
				pree(v, u), implDFS(u, visit, pre, post, pree, poste, faile), poste(v, u);
			else
				faile(v, u);
		post(v);
	}
	struct Edge { int dst, weight; operator int() const { return dst; } };
	Graph(int n):edges(n){}
	void addEdge1(int a, int b, int w) { edges[a].push_back(Edge{b, w}); }
	int size() const { return (int)edges.size(); }
	Graph reversed() const {
		auto gr = Graph(size());
		for (auto v=0; v<size(); ++v)
			for (auto edge : edges[v])
				gr.addEdge1(edge.dst, v, edge.weight);
		return gr;
	}
	vector<long long> dijkstra(int source) const {
		auto dist = vector<long long>(size(), numeric_limits<long long>::max() / 2);
		dist[source] = 0ll;
		auto comp = [&](int v1, int v2){ return tie(dist[v1], v1) < tie(dist[v2], v2); };
		auto que = set<int, decltype(comp)>({source}, comp);
		while (not que.empty()) {
			auto v = *que.begin();
			que.erase(que.begin());
			for (auto e : edges[v])
				if (dist[e.dst] > dist[v] + e.weight) {
					if (que.count(e.dst))
						que.erase(que.find(e.dst));
					dist[e.dst] = dist[v] + e.weight;
					que.insert(e.dst);
				}
		}
		return dist;
	}
	bool hasNegativeCycle() const {
		auto dist = vector<long long>(size(), 0ll);
		for (auto phase=0; phase<size()-1; ++phase)
			for (auto v=0; v<size(); ++v)
				for (auto edge : edges[v])
					dist[edge] = min(dist[edge], dist[v] + edge.weight);
		for (auto v=0; v<size(); ++v)
			for (auto edge : edges[v])
				if (dist[edge] > dist[v] + edge.weight)
					return true;
		return false;
	}
	vector<vector<Edge>> edges;
};

Graph loadGraph(int n, int m) {
	auto g = Graph(n);
	while (m --> 0) {
		auto v = load<int>() - 1;
		auto u = load<int>() - 1;
		auto w = load<int>();
		g.addEdge1(v, u, w);
	}
	return g;
}

void cleanIrrelevant(int n, Graph& g) {
	auto gr = g.reversed();
	auto reach1 = vector<bool>(n, false);
	auto reachN = vector<bool>(n, false);
	g.DFS(0, [&](int v){
		reach1[v] = true;
	}, {}, {}, {}, {});
	gr.DFS(n-1, [&](int v){
		reachN[v] = true;
	}, {}, {}, {}, {});
	for (auto v=0; v<n; ++v)
		if (not (reach1[v] and reachN[v]))
			g.edges[v].clear();
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	auto n = load<int>();
	auto m = load<int>();
	auto p = load<int>();
	auto g = loadGraph(n, m);
	for (auto v=0; v<n; ++v)
		for (auto& edge : g.edges[v])
			edge.weight = p - edge.weight;
	cleanIrrelevant(n, g);
	if (not g.hasNegativeCycle()) {
		auto dist = g.dijkstra(0);
		cout << max(-dist[n-1], 0ll) << '\n';
	} else {
		cout << "-1\n";
	}
}


Measured memory_bytes: 640