#include <bits/stdc++.h>
using namespace std; inline void fileio(const char* in, const char* out) { freopen(in, "r", stdin); freopen(out, "w", stdout); } 
#define TD typedef
#define forx(i,n) for(int i = 0; i < (n); ++i)
TD long long ll; TD long double ld; TD pair<int,int> pii; TD pair<ll, ll> pll; TD vector<int> VI; TD vector<bool> VB; TD vector<ll> VL;
const char nl = '\n'; const int INF = 0x3f3f3f3f; const ll LINF = 0x3f3f3f3f3f3f3f3fll; const ld EPS = 1e-9, PI = acos(-1);
#define ff first
#define ss second

// INITIALIZATION:
// Graph(N,D)
//    constructs a graph with 'N' nodes and Edge dimension 'D', ie. edges can hold 'D' long long data values
// add_edge(u,v, [undirected], [data])
//    adds an edge from 'u' to 'v' (undirected by default) and with the optionally given intial edge data values
//
// Edge:
//   operator[i] returns the ith data value associated with this edge (by reference)
//   nodeFrom(f) returns the node that would be reached from node 'f' via this edge.
// 
// USAGE:
// Graph algorithms will take in a graph, relevant inputs (eg. source and target node) as well as data indices. eg. wIdx, cIdx
// These indicate which index the edge data is stored in. eg. wIdx=0 means edge weights will be accessed using Edge[0];
struct Graph {
  class Edge { Graph* owner; const int idx; public: const int u, v; Edge() : owner(0), idx(-1), u(-1), v(-1) { } Edge(Graph* owner, int idx, int u, int v) :
    owner(owner), idx(idx), u(u), v(v) { }
    ll& operator[](int i) { return owner->getEdgeData(idx, i); }
    ll operator[](int i) const { return owner->getEdgeData(idx, i); }
    int nodeFrom(int f) const { return f^u^v; } }; TD vector<Edge> VE;
  class EdgeIt { VI* adj; VE* edge_list; public: EdgeIt(VI* adj, VE* edge_list) : adj(adj), edge_list(edge_list) {}
    class Iterator { VI* adj; VE* edge_list; int idx; public: Iterator(VI* adj, VE* edge_list, int idx=0) : adj(adj), edge_list(edge_list), idx(idx) {}
    bool operator == (const Iterator& b) const { return adj == b.adj && idx == b.idx; } bool operator != (const Iterator& b) const { return !(*this == b); }
    Iterator operator ++() { auto temp = *this; ++idx; return temp; } Edge& operator *() { return (*edge_list)[(*adj)[idx]]; } };
    Iterator begin() const { return Iterator(adj, edge_list); } Iterator end() const { return Iterator(adj, edge_list, adj->size()); } };
  class NodeIt { EdgeIt it; int u; public: NodeIt(VI* adj, VE* edge_list, int u) : it(adj, edge_list), u(u) {} class Iterator { EdgeIt::Iterator iter; int u;
    public: Iterator(EdgeIt::Iterator iter, int u) : iter(iter), u(u) { } bool operator == (const Iterator& b) const { return iter == b.iter && u == b.u; }
    bool operator != (const Iterator& b) const { return !(*this == b); } Iterator operator ++() { auto temp = *this; ++iter; return temp; }
    int operator *() { return (*iter).nodeFrom(u); } }; Iterator begin() const { return Iterator(it.begin(), u); }
    Iterator end() const { return Iterator(it.end(), u); } };

  Graph(int N, int D=0) : edge_list(0), adj_list(N), edge_data(0), dimens(D) { edge_list.reserve(N); edge_data.reserve(D*N); }
  Edge& add_edge(int u, int v, bool undirected=true, initializer_list<ll> data = { }) {
    int i = edge_list.size();
    adj_list[u].push_back(i);
    if (undirected)
      adj_list[v].push_back(i);
    edge_list.emplace_back(this, i, u, v);
    int j = edge_data.size();
    edge_data.resize(j+dimens);
    for (ll val : data) edge_data[j++] = val;
    return edge_list.back();
  }
  ll& getEdgeData(int eIdx, int dIdx) { static ll dummy; return (dIdx < 0 || dIdx >= dimens) ? dummy : edge_data[eIdx*dimens + dIdx]; }
  // Number of nodes and edges, and dimension of each edge respectively
  ll N() const { return adj_list.size(); }
  ll M() const { return edge_list.size(); }
  ll D() const { return dimens; }
  // AdjVec is the edge indices
  const VI& getAdjVec(int u) const { return adj_list[u]; }
  EdgeIt getAdjEdge(int u) { return EdgeIt(&adj_list[u], &edge_list); }
  NodeIt getAdjNode(int u) { return NodeIt(&adj_list[u], &edge_list, u); }
  const VE& edges() const { return edge_list; }
  // Degree of a node (for directed graph, out degree)
  int degree(int u) const { return adj_list[u].size(); }
  Edge& getEdge(int i) { return edge_list[i]; }
  Edge& operator[](int i) { return edge_list[i]; }

  // Returns the transpose of the graph
  // (All directed edges flipped)
  Graph transpose() const {
    Graph ret(N(), D());
    for (const Edge& e : edges()) {
      Edge& temp = ret.add_edge(e.v, e.u, false);
      forx(i,D()) temp[i] = e[i];
    }
    return ret;
  }

  // returns true if u's only neighbor is p
  bool isLeaf(int u, int p) const { return adj_list[u].size() == 1 && edge_list[adj_list[u][0]].nodeFrom(u) == p; }
private: VE edge_list; vector<VI> adj_list; VL edge_data; const int dimens; }; typedef Graph::Edge Edge;

int n;

// Single Source Shortest Path w/ negative weights
// s - source node
// d - distances
// wIdx - index to retrieve edge weights from
// returns true if negative weight cycle exists
bool bFord(const Graph& graph, int s, VL& d, int wIdx=0) {
  d.assign(graph.N(), LINF); d[s] = 0;
  forx (i, graph.N())
    for (const Edge& e : graph.edges()) {
      if (d[e.u] == LINF) continue;
      if (d[e.v] > d[e.u] + e[wIdx]) {
        if (i == graph.N() - 1)
          return true;
        d[e.v] = d[e.u] + e[wIdx];
      }
    }
  return false;
}

// Single Source/Target Shortest Path w/ negative weights
// s - source
// t - target
// wIdx - index to retrieve edge weights from
// returns min weight path from s to t if it exists. otherwise, LINF
ll bFordSingleTarget(const Graph& graph, int s, int t, int wIdx=0) {
  //first bFord to check if
  VL temp; bFord(graph.transpose(), t, temp, wIdx);
  VB revReach(temp.size()); //reachable from t in transpose
  forx(i, temp.size()) revReach[i] = (temp[i] < LINF);
  bFord(graph, s, temp, wIdx);
  forx(i, temp.size()) if (temp[i] >= LINF) revReach[i] = false;
  VL d(graph.N(), LINF); d[s] = 0;
  forx(i, graph.N()) {
    for (const Edge& e : graph.edges()) {
      if (!revReach[e.v] || !revReach[e.u]) continue;
      if (d[e.u] == LINF) continue;
      if (d[e.v] > d[e.u] + e[wIdx]) {
        if (i == graph.N() - 1) return LINF;
        d[e.v] = d[e.u] + e[wIdx];
      }
    }
  }
  return d[t];
}

int main() {
  atexit([](){ cerr << "Time: " << (ld)clock() / CLOCKS_PER_SEC << nl; });
  ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  // Emily <3
  int m, p;
  cin >> n >> m >> p;
  Graph graph(n+1, 1);
  forx(i, m) {
    int a,b,c;
    cin >> a >> b >> c;
    graph.add_edge(a, b, false, {p - c});
  }

  ll ans = bFordSingleTarget(graph, 1, n);
  if (ans != LINF) {
    ans *= -1;
    if (ans < 0) ans = 0;
    cout << ans << nl;
  } else {
    cout << "-1" << nl;
  }

  
  return 0;
}


Measured memory_bytes: 1024