#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using VI = vector<int>;
using VL = vector<ll>;
#define FOR(i,a,n) for(int (i)=(a);(i)<(n);(i)++)
#define eFOR(i,a,n) for(int (i)=(a);(i)<=(n);(i)++)
#define SORT(i) sort((i).begin(),(i).end())
#define rSORT(i,a) sort((i).begin(),(i).end(),(a))
#define CIN(v,n) for(int i=0;i<(n);i++){cin>>v[i];}
#define COUT(v,n) for(int i=0;i<v.size();i++){cout<<v[i]<<(i == v.size()-1 ?'\n':' ');}
constexpr ll INF = 1000000000;
constexpr ll LLINF = 1LL << 60;
constexpr ll mod = 1000000007;
constexpr ll MOD = 998244353;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; }return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; }return 0; }
inline void init() { cout.tie(nullptr); cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); }

struct edge {
    int from, to; ll cost;
    edge(int s, int d, ll w) : from(s), to(d), cost(w) {}
};

ll POW(ll n, ll p) {
    if (!p) return 1;
    if (!(p % 2)) {
        ll t = POW(n, p / 2);
        return t * t % mod;
    }
    return n * POW(n, p - 1);
}

ll gcd(ll a, ll b) {
    if (b == 0)return a;
    return gcd(b, a % b);
}
ll lcm(ll a, ll b) {
    return a * b / gcd(a, b);
}

bool isPrime(ll n) {
    if (n < 2)return false;
    for (ll i = 2; i * i <= n; i++)if (!(n % i))return false;
    return true;
}

vector<ll> dijkstra(int i, vector<vector<edge>> graph) {
    //i:始点
    //graph:重み付きグラフ
    int n = graph.size();
    vector<ll> d(n, LLINF);
    d[i] = 0;
    priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> q;
    q.push(make_pair(0, i));//第一引数:コスト 第二引数:頂点
    while (!q.empty()) {
        pair<ll, int> p = q.top();
        q.pop();
        int v = p.second;
        if (d[v] < p.first) {
            continue;
        }
        for (auto x : graph[v]) {
            if (d[x.to] > d[v] + x.cost) {
                d[x.to] = d[v] + x.cost;
                q.push(make_pair(d[x.to], x.to));
            }
        }
    }
    return d;
}
bool Bellman_Ford(int start, int E, int V, vector<edge> Edge, vector<ll>& d) {
    //第一引数:start 始点
    //第二引数:E 辺の数
    //第三引数:V 頂点数
    //第四引数:Edge 辺の重み付きのグラフ
    //第五引数:d 各頂点への距離を入れる配列(答えが入る)
    fill(d.begin(), d.end(), LLINF);
    d[start] = 0;
    vector<bool> t(V, false);
    for (int i = 0; i < V - 1; i++) {
        for (int j = 0; j < E; j++) {
            edge e = Edge[j];
            if (d[e.from] == LLINF) { continue; }
            if (d[e.to] > d[e.from] + e.cost) {
                d[e.to] = d[e.from] + e.cost;
            }
        }
    }

    for (int i = 0; i < V; i++) {
        for (int j = 0; j < E; j++) {
            edge e = Edge[j];
            if (d[e.from] == LLINF) { continue; }
            if (d[e.to] > d[e.from] + e.cost) {
                d[e.to] = d[e.from] + e.cost;
                t[e.to] = true;
                /*
                if (i == V - 1) {//どこかに閉路があることを感知する
                    return false;
                }
                */
            }
            if (t[e.from]) {
                t[e.to] = true;
            }
        }
    }
    if (t[V - 1]) {
    //V-1は頂点番号n-1で、始点からn-1までに負の閉路を検出したい場合には、
    //コメントアウトを解除すること。
        return false;
    }
    return true;
}
bool topological_sort(const vector<vector<edge>>& g, vector<int>& ans) {
    //トポロジカルソート
    //trueが帰る時、トポロジカルソートが成功し、その結果がansに渡される
    //falseはトポロジカルソートの失敗
    int n = g.size(), k = 0;
    vector<int> ord(n), in(n);
    for (auto& es : g) {
        for (auto& e : es) {
            in[e.to]++;
        }
    }
    queue<int> q;
    for (int i = 0; i < n; ++i) {
        if (in[i] == 0) q.push(i);
    }
    while (!q.empty()) {
        int v = q.front();
        q.pop();
        ord[k++] = v;
        for (auto& e : g[v]) {
            if (--in[e.to] == 0) q.push(e.to);
        }
    }
    ans = ord;
    if (*max_element(in.begin(), in.end()) == 0) { return true; }
    return false;
}
vector<int> articulationPoint(const vector<vector<edge>>& g) {
    //グラフの関節点を列挙する
    //最後の2行で、erace uniqueをしない場合は、その分割によって何個のグラフに分かれるかを判定できる(要チェック)。
    int n = g.size(), idx;
    vector<int> low(n), ord(n), art;
    function<void(int)> DFS = [&](int v) {
        low[v] = ord[v] = ++idx;
        for (auto& e : g[v]) {
            int w = e.to;
            if (ord[w] == 0) {
                DFS(w);
                low[v] = min(low[v], low[w]);
                if ((ord[v] == 1 && ord[w] != 2) || (ord[v] != 1 && low[w] >= ord[v])) {
                    art.push_back(v);
                }
            }
            else {
                low[v] = min(low[v], ord[w]);
            }
        }
    };
    for (int u = 0; u < n; u++) {
        if (ord[u] == 0) {
            idx = 0;
            DFS(u);
        }
    }

    sort(art.begin(), art.end());//えられた関節点をソート
    art.erase(unique(art.begin(), art.end()), art.end());//同じ関節点が複数存在することがある,

    return art;
}

const int nCk_MAX = 510000;
ll fac[nCk_MAX], finv[nCk_MAX], inv[nCk_MAX];
bool Preparation = true;
void cominit() {
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (int i = 2; i < nCk_MAX; i++) {
        fac[i] = fac[i - 1] * i % mod;
        inv[i] = mod - inv[mod % i] * (mod / i) % mod;
        finv[i] = finv[i - 1] * inv[i] % mod;
    }
}
ll com(int n, int k) {
    if (Preparation) {
        cominit();
        Preparation = false;
    }
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * (finv[k] * finv[n - k] % mod) % mod;
}

int main() {
    init();

    int n, m;
    ll p;
    cin >> n >> m >> p;
    int a, b;
    ll c;
    vector<edge> g;
    FOR(i, 0, m) {
        cin >> a >> b >> c;
        g.push_back({ --a, --b, p - c });
    }

    vector<ll> ans(n);

    if (Bellman_Ford(0, m, n, g, ans))cout << max(-ans[n - 1], 0LL) << "\n";
    else cout << "-1\n";
}


Measured memory_bytes: 512