#include<bits/stdc++.h>
using namespace std;
#pragma region atcoder
/*#include <atcoder/scc>
using namespace atcoder;
//using mint = modint1000000007;
//These are for segment tree
/*int op(int a, int b){return max(a, b);}
int e(){return -1;}
bool f(int v){ return v < target;}
*/
#pragma endregion
#pragma region macros
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vs = vector<string>;
using vl = vector<ll>;
using vb = vector<bool>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<ll>>;
#define rep(i, n) for(int i = 0; i < n; i++)
#define rrep(i, n) for(int i = n - 1; i >= 0; i--)
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())
#pragma endregion
#pragma region debug for var, v, vv
#define debug(var)  do{std::cout << #var << " : ";view(var);}while(0)
template<typename T> void view(T e){std::cout << e << std::endl;}
template<typename T> void view(const std::vector<T>& v){for(const auto& e : v){ std::cout << e << " "; } std::cout << std::endl;}
template<typename T> void view(const std::vector<std::vector<T> >& vv){cout << endl;int cnt = 0;for(const auto& v : vv){cout << cnt << "th : "; view(v); cnt++;} cout << endl;}
#pragma endregion

const ll mod = 1000000007;
const int inf = 1001001001;
const ll INF = 1001001001001001001;
const int MAX = 2000005;

template<class T>bool chmax(T &a, const T b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T b) { if (b<a) { a=b; return 1; } return 0; }
ll modpow(ll a, ll p){ll ret = 1; while(p){if(p & 1){ret = ret * a % mod;} a = a * a % mod; p >>= 1;} return ret;}

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};

/*-----------------------------------------------------------------------------------------------------*/
// from is the departure point, to means the destination and cost is the weight of an edge
struct Edge{ll from, to, cost;};

struct graph{
    ll num;
    vector<Edge> G;
    vector<ll> dist;
	vector<bool> negative;
    // constructor for initialization
    graph(ll n) : num(n), dist(n), negative(n){}
    // assembling a graph whose edge is coming from s to t
    void add_edge(ll s, ll t, ll cost){
        Edge e;
        e.from = s;
        e.to = t;
        e.cost = cost;
        G.push_back(e);
    }    
    // Bellman-Ford algorithm
    // O(|V||E|)
    // you can use this even when a graph contains a negative weighted path
    void Bellman_Ford(ll s){
        for(int i = 0; i < num; i++){
            dist[i] = INF;
        }
        dist[s] = 0;
        for(int i = 0; i < num - 1; i++){
            for(int j = 0; j < G.size(); j++){
                Edge e = G[j];
				//自己ループの負辺があったら、dist[e.from] == INFを入れないとsから辿り着く前に勝手に更新されるので誤った答えになりうる
                if(dist[e.from] != INF && dist[e.to] > dist[e.from] + e.cost){
                    dist[e.to] = dist[e.from] + e.cost;
                    /*if(i == num - 1){
                        dist[num - 1] = INF;
						break;
                    }*/
                }
            }
        }
    }
	// after Bellman-Ford algorithm (we assume the shortest paths have to be determined so far)
	// find negative roops along the path from s to each vertex.
	void find_negative(){
		for(int i = 0; i < num; i++) negative[i] = false;
		for(int i = 0; i < num; i++){
			for(int j = 0; j < G.size(); j++){
				Edge e = G[j];
				//自己ループの負辺があると、sから辿り着けない頂点からの影響が生じる
				//この時点でdistがINFならsから行けない
				if(dist[e.from] != INF && dist[e.from] + e.cost < dist[e.to]){
					dist[e.to] = dist[e.from] + e.cost;
					negative[e.to] = true;
				}
				if(negative[e.from]) negative[e.to] = true;
			}
		}
	}
};

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	int n, m, p; cin >> n >> m >> p;
	graph G(n);
	rep(i,m){
		ll a, b, c; cin >> a >> b >> c;
		--a, --b;
		G.add_edge(a, b, -(c - p));
	}
	G.Bellman_Ford(0);
	G.find_negative();
	ll ans = max(0ll, -G.dist[n - 1]);
	cout << (G.negative[n - 1] ? -1 : ans) << endl;
}

Measured memory_bytes: 3804