Problem:
 Score : 500 points    Problem Statement There is a directed graph with N vertices numbered 1 to N and M edges.
The i -th edge is directed from Vertex A_i to Vertex B_i , and there are C_i coins placed along that edge.
Additionally, there is a button on Vertex N .  We will play a game on this graph.
You start the game on Vertex 1 with zero coins, and head for Vertex N by traversing the edges while collecting coins.
It takes one minute to traverse an edge, and you can collect the coins placed along the edge each time you traverse it.
As usual in games, even if you traverse an edge once and collect the coins, the same number of coins will reappear next time you traverse that edge, which you can collect again.  When you reach Vertex N , you can end the game by pressing the button. (You can also choose to leave Vertex N without pressing the button and continue traveling.)
However, when you end the game, you will be asked to pay T \times P coins, where T is the number of minutes elapsed since the start of the game. If you have less than T \times P coins, you will have to pay all of your coins instead.  Your score will be the number of coins you have after this payment.
Determine if there exists a maximum value of the score that can be obtained. If the answer is yes, find that maximum value.      Constraints  2 \leq N \leq 2500  1 \leq M \leq 5000  1 \leq A_i, B_i \leq N  1 \leq C_i \leq 10^5  0 \leq P \leq 10^5  All values in input are integers.  Vertex N can be reached from Vertex 1 .         Input Input is given from Standard Input in the following format:  N  M  P  A_1  B_1  C_1  :  A_M  B_M  C_M       Output If there exists a maximum value of the score that can be obtained, print that maximum value; otherwise, print -1 .        Sample Input 1 3 3 10
1 2 20
2 3 30
1 3 45      Sample Output 1 35   There are two ways to travel from Vertex 1 to Vertex 3 :   Vertex 1 \rightarrow 2 \rightarrow 3 : You collect 20 + 30 = 50 coins on the way. After two minutes from the start of the game, you press the button, pay 2 \times 10 = 20 coins, and you have 50 - 20 = 30 coins left.  Vertex 1 \rightarrow 2 : You collect 45 coins on the way. After one minute from the start of the game, you press the button, pay 1 \times 10 = 10 coins, and you have 45 - 10 = 35 coins left.   Thus, the maximum score that can be obtained is 35 .       Sample Input 2 2 2 10
1 2 100
2 2 100      Sample Output 2 -1   The edge extending from Vertex 1 takes you to Vertex 2 . If you then traverse the edge extending from Vertex 2 to itself t times and press the button, your score will be 90 + 90t . Thus, you can infinitely increase your score, which means there is no maximum value of the score that can be obtained.       Sample Input 3 4 5 10
1 2 1
1 4 1
3 4 1
2 2 100
3 3 100      Sample Output 3 0   There is no way to travel from Vertex 1 to Vertex 4 other than traversing the edge leading from Vertex 1 to Vertex 4 directly. You will pick up one coin along this edge, but after being asked to paying 10 coins, your score will be 0 .  Note that you can collect an infinite number of coins if you traverse the edge leading from Vertex 1 to Vertex 2 , but this is pointless since you can no longer reach Vertex 4 and end the game.

Solution (Python):
import sys
from collections import deque

input = sys.stdin.readline

class Bellman_Ford:
    def __init__(self, v=None, e=None, lis=None, start=None, end=None, inf=float('inf')):
        self.V = v
        self.E = e
        self.lis = lis
        self.start = start if start else 0
        self.end = end if end else self.V-1
        self.inf = inf
        self.close_minus = False
    
    def getlist(self, lis):
        self.lis = lis
    
    def def_start(self, s):
        self.start = s
    
    def def_end(self, e):
        self.end = e

    def def_inf(self, inf):
        self.inf = inf
    
    def def_vertice(self, v):
        self.V = v
    
    def def_edge(self, e):
        self.E = e

    def prepare(self):
        self.cost = [self.inf]*self.V 
        self.cost[self.start] = 0 

    def search(self):
        for i in range(self.V):
            update = False 
            for x, y, z in self.lis:
                if self.cost[y] > self.cost[x] + z:
                    self.cost[y] = self.cost[x] + z
                    update = True
            if not update:
                break
            
            if i == self.V - 1:
                self.close_minus = True
                return False
        return True

    def main(self):
        self.prepare()
        self.search()
    
    def cost_all(self):
        return self.cost

def main():
    n, m, p = map(int, input().split())
    
    graph = [None]*m
    tree_forth = [[] for _ in range(n)]
    tree_back = [[] for _ in range(n)]
    
    for i in range(m):
        a, b, c =map(int, input().split())
        tree_forth[a-1].append(b-1)
        tree_back[b-1].append(a-1)
        c = p-c
        graph[i] = (a-1, b-1, c)
    
    already1, already2 = [True]*n, [True]*n
    for already, tree, start in zip([already1, already2], [tree_forth, tree_back], [0, n-1]):
        not_yet = deque([start])
        already[start] = False
        while not_yet:
            key = not_yet.pop()
            for v in tree[key]:
                if already[v] == False:
                    continue
                already[v] = False
                not_yet.append(v)
    
    graph_new = []
    for i in range(m):
        a, b, c = graph[i]
        if already1[a] or already1[b] or already2[a] or already2[b]:
            continue
        graph_new.append((a, b, c))
       
    bf = Bellman_Ford(v=n, e=m, lis=graph_new)
    bf.main()
    if bf.close_minus:
        print(-1)
    else:
        print(max(0, -bf.cost[n-1]))
    
    
    
if __name__ == "__main__":
    main()

Solution (Python):
import sys
from collections import deque

input = sys.stdin.readline

class Bellman_Ford:
    def __init__(self, v=None, e=None, lis=None, start=None, end=None, inf=float('inf')):
        self.V = v
        self.E = e
        self.lis = lis
        self.start = start if start else 0
        self.end = end if end else self.V-1
        self.inf = inf
        self.close_minus = False
    
    def getlist(self, lis):
        self.lis = lis
    
    def def_start(self, s):
        self.start = s
    
    def def_end(self, e):
        self.end = e

    def def_inf(self, inf):
        self.inf = inf
    
    def def_vertice(self, v):
        self.V = v
    
    def def_edge(self, e):
        self.E = e

    def prepare(self):
        self.cost = [self.inf]*self.V 
        self.cost[self.start] = 0 

    def search(self):
        for i in range(self.V):
            update = False 
            for x, y, z in self.lis:
                if self.cost[y] > self.cost[x] + z:
                    self.cost[y] = self.cost[x] + z
                    update = True
            if not update:
                break
            
            if i == self.V - 1:
                self.close_minus = True
                return False
        return True

    def main(self):
        self.prepare()
        self.search()
    
    def cost_all(self):
        return self.cost

def main():
    n, m, p = map(int, input().split())
    
    graph = [None]*m
    tree_forth = [[] for _ in range(n)]
    tree_back = [[] for _ in range(n)]
    
    for i in range(m):
        a, b, c =map(int, input().split())
        tree_forth[a-1].append(b-1)
        tree_back[b-1].append(a-1)
        c = p-c
        graph[i] = (a-1, b-1, c)
    
    already1, already2 = [True]*n, [True]*n
    for already, tree, start in zip([already1, already2], [tree_forth, tree_back], [0, n-1]):
        not_yet = deque([start])
        already[start] = False
        while not_yet:
            key = not_yet.pop()
            for v in tree[key]:
                if already[v] == False:
                    continue
                already[v] = False
                not_yet.append(v)
    
    graph_new = []
    for i in range(m):
        a, b, c = graph[i]
        if already1[a] or already1[b] or already2[a] or already2[b]:
            continue
        graph_new.append((a, b, c))
       
    bf = Bellman_Ford(v=n, e=m, lis=graph_new)
    bf.main()
    if bf.close_minus:
        print(-1)
    else:
        print(max(0, -bf.cost[n-1]))
    
    
    
if __name__ == "__main__":
    main()

Solution (Python):
import sys
import numpy as np
from scipy.sparse.csgraph import bellman_ford, connected_components
input = sys.stdin.readline


def main():
    n, m, p = map(int, input().split())
    
    l = np.zeros((n, n))
    for i in range(m):
        a, b, c =map(int, input().split())
        c = p-c
        if c == 0:
            c = 10**(-7.9)
        if l[a-1][b-1] == 0:
            l[a-1][b-1] = c
        else:
            l[a-1][b-1] = min(l[a-1][b-1], c)
    x = l[-1, 0]
    l[-1][0] = 10**(-7.9)
    n, labels = connected_components(l, connection="strong")
    l = l[labels == labels[0]][:, labels == labels[0]]
    l[-1, 0] = x
    
    try:
        print(max(0, int(round(bellman_ford(l, indices=0)[-1]))*(-1)))
    except:
        print(-1)


if __name__ == "__main__":
    main()

Solution (Python):

import sys


def solve(N: int, M: int, P: int, A: "List[int]", B: "List[int]", C: "List[int]"):
    import numpy as np
    from scipy.sparse import csr_matrix
    from scipy.sparse.csgraph import bellman_ford, NegativeCycleError

    def to_csr_matrix(X, Y, Z, shape, dtype):
        d = {}
        for x, y, z in zip(X, Y, Z):
            d[(x, y)] = max(d.get((x, y), -float("inf")), z)
        ind, data = zip(*d.items())
        return csr_matrix((data, zip(*ind)), shape=shape, dtype=dtype)

    smat = bellman_ford(csr_matrix((C, (A, B)), shape=(N+1, N+1), dtype=np.int32),
                        directed=True, unweighted=True, indices=1)
    tmat = bellman_ford(csr_matrix((C, (B, A)), shape=(N+1, N+1), dtype=np.int32),
                        directed=True, unweighted=True, indices=N)
    r = set([i for i, v in enumerate(smat + tmat) if not np.isinf(v)])
    A, B, C = zip(*[(a, b, c) for a, b, c in zip(A, B, C) if b in r])
    try:
        csr_mat = to_csr_matrix(A, B, C, (N+1, N+1), np.float64)
        csr_mat.data = P - csr_mat.data
        return -min(int(bellman_ford(csr_mat, directed=True, indices=1)[N]), 0)
    except NegativeCycleError:
        return -1


def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  
    M = int(next(tokens))  
    P = int(next(tokens))  
    A = [int()] * (M)  
    B = [int()] * (M)  
    C = [int()] * (M)  
    for i in range(M):
        A[i] = int(next(tokens))
        B[i] = int(next(tokens))
        C[i] = int(next(tokens))
    print(solve(N, M, P, A, B, C))

if __name__ == '__main__':
    main()

Solution (Python):
n,m,p = map(int, input().split())
G = []
for i in range(m):
    a,b,c = map(int, input().split())
    G.append([a,b,c-p])

def bellmanFord(G, start_vertex):
    distance = [-float('inf') for i in range(n+1)]
    distance[start_vertex] = 0
    for i in range(2*n):
        for node,neighbor,cost in G:
            if distance[neighbor] < distance[node] + cost:
                if i < n:
                    distance[neighbor] = distance[node] + cost
                else:
                    distance[neighbor] = float('inf')
        if i == n-1:
            prev_ans = distance[n]
    if prev_ans != distance[n]:
        return -1
    else:
        return distance[n]

distance = bellmanFord(G, 1)
if distance == -1:
    ans = -1
else:
    ans = max(0, distance)
print(ans)

Solution (Python):
import sys
sys.setrecursionlimit(10**9)
input = sys.stdin.readline

N, M, P = map(int, input().split())

edges = []
for _ in range(M):
    a, b, c = map(int, input().split())
    edges.append([a-1, b-1, -c+P])


def bellnabFord(edges, src, N):
    inf = float('inf')
    dist = [inf for i in range(N)]
    dist[src] = 0

    for i in range(2*N):
        for s, d, c in edges:
            if dist[d] > dist[s]+c:
                dist[d] = dist[s]+c
                if i >= N: 
                    dist[d] = -float('inf')

            if i == N-1:
                prev = dist[-1]
    return (prev, dist[-1])


prev, dist = bellnabFord(edges, 0, N)
if prev != dist:
    ans = -1
else:
    ans = max(0, -dist)
print(ans)

Solution (Python):
import sys
sys.setrecursionlimit(10**9)
input = sys.stdin.readline

N, M, P = map(int, input().split())

edges = []
for _ in range(M):
    a, b, c = map(int, input().split())
    edges.append([a-1, b-1, -c+P])


def bellnabFord(edges, src, N):
    inf = float('inf')
    dist = [inf for i in range(N)]
    dist[src] = 0

    for i in range(2*N):
        for s, d, c in edges:
            if s != inf and dist[d] > dist[s]+c:
                dist[d] = dist[s]+c
                if i >= N: 
                    dist[d] = -float('inf')

            if i == N-1:
                prev = dist[-1]
    return (prev, dist[-1])


prev, dist = bellnabFord(edges, 0, N)
if prev != dist:
    ans = -1
else:
    ans = max(0, -dist)
print(ans)

Solution (Python):
import sys
input = sys.stdin.readline
from collections import *

def bfs(s, g):
    q = deque([s])
    dist = [-1]*N
    dist[s] = 0
    
    while q:
        v = q.popleft()
        
        for nv in g[v]:
            if dist[nv]==-1:
                dist[nv] = dist[v]+1
                q.append(nv)
    
    return dist

def bellman_ford():
    dist = [10**18]*N
    dist[0] = 0
    
    for i in range(N):
        for s, t, w in edges:
            if d1[s]==-1 or d2[t]==-1:
                continue
            
            if dist[t]>dist[s]+w:
                dist[t] = dist[s]+w
                
                if i==N-1:
                    print(-1)
                    exit()
        
    return -dist[N-1]
    
N, M, P = map(int, input().split())
G = [[] for _ in range(N)]
rG = [[] for _ in range(N)]
edges = []

for _ in range(M):
    A, B, C = map(int, input().split())
    G[A-1].append(B-1)
    rG[B-1].append(A-1)
    edges.append((A-1, B-1, -(C-P)))

d1 = bfs(0, G)
d2 = bfs(N-1, rG)
print(max(0, bellman_ford()))

Solution (Python):
n,m,p=map(int,input().split())
g=[[] for _ in range(n)]
e=[]
for _ in range(m):
  a,b,c=map(int,input().split())
  a,b=a-1,b-1
  c-=p
  g[a].append([b,c])
  e.append([a,b,-c])







def BellmanFord(edges,num_v,source):
  
  inf=float("inf")
  dist=[inf for i in range(num_v)]
  dist[source]=0  
  
  for i in range(num_v-1):
    for edge in edges:
      if dist[edge[0]] != inf and dist[edge[1]] > dist[edge[0]] + edge[2]:
        dist[edge[1]] = dist[edge[0]] + edge[2]
        if i==num_v-1: return -1
  
  negative=[False]*n
  for i in range(num_v):
    for edge in edges:
      if negative[edge[0]]:negative[edge[1]]=True
      if dist[edge[0]] != inf and dist[edge[1]] > dist[edge[0]] + edge[2]:
        negative[edge[1]] = True
  return dist[n-1],negative[n-1]
d,n=BellmanFord(e,n,0)
if n:
  print(-1)
else:
  print(max(0,-d))

Solution (Python):
import sys
sys.setrecursionlimit(10000)

N,M,P=map(int,input().split())
ways=[[] for _ in range(N)]
Rways=[[] for _ in range(N)]

for i in range(M):
  A,B,C=map(int,input().split())
  ways[A-1].append([B-1,C-P])
  Rways[B-1].append(A-1)
  
  
visited=[-float("inf")]*N
visited[0]=0

blacklist=[True]*N
blacklist[-1]=False
"""
for c in range(M):
  for i in range(N):
    if blacklist[i]==True:
      continue
    for to in Rways[i]:
      blacklist[to]=False
"""
def b_update(nord):
  global blacklist
  for to in Rways[nord]:
    if blacklist[to]==True:
      blacklist[to]=False
      b_update(to)
      
b_update(N-1)

for c in range(N):
  flag=False
  for i in range(N):
    debit=visited[i]
    if debit==-float("inf"):
      continue
    for to,cost in ways[i]:
      if visited[to]<debit+cost and not blacklist[to]:
        visited[to]=debit+cost
        flag=True
        
  if not flag:
    break
  if c==N-1:
    print(-1)
    exit()
      
ans=visited[-1]
if ans==-float("inf"):
  print(-1)
else:
  print(max(ans,0))

Solution (Python):
import sys
input = sys.stdin.readline


class Graph:
    class Edge:
        def __init__(self, to, cost):
            """
            :param to:  終点ノード
            :param cost: 辺の重み
            """
            self.to, self.cost = to, cost

    def __init__(self, n, directed=False, decrement=True, edges=[]):
        self.n = n
        self.directed = directed
        self.decrement = decrement
        self.edges2 = []
        self.parent = [-1]*self.n
        self.info = [-1]*self.n
        for x, y, cost in edges:
            self.add_edge(x, y, cost)

    def add_edge(self, x, y, cost):
        if self.decrement:
            x -= 1
            y -= 1
        self.edges2.append((x, y, cost))
        if self.directed == False:
            self.edges2.append((y, x, cost))

    def bellman_ford(self, start, INF=10**18):
        """
        :return: 負の閉路が存在する場合は -1 を返す
        """
        dist = [INF] * self.n
        if self.decrement:
            start -= 1
        dist[start] = 0
        for cnt in range(self.n):
            for x, y, cost in self.edges2:
                if dist[x] != INF and dist[x] + cost < dist[y]:
                    if cnt == self.n - 1:
                        return -1
                    dist[y] = dist[x] + cost
        return dist

    def bellman_ford2(self, start, goal, INF=10**18):
        """
        :return: 負の閉路が存在する場合は -1 を返す
        """
        dist = [INF] * self.n
        if self.decrement:
            start -= 1
            goal -= 1
        dist[start] = 0
        for cnt in range(2*self.n):
            for x, y, cost in self.edges2:
                if dist[x] != INF and dist[x] + cost < dist[y]:
                    dist[y] = dist[x] + cost
                    if cnt >= self.n:
                        dist[y] = -INF
                if cnt == self.n - 1:
                    res = dist[goal]
        if res == dist[goal]:
            return res

    def draw(self):
        """
        :return: グラフを可視化
        """
        import matplotlib.pyplot as plt
        import networkx as nx

        if self.directed:
            G = nx.DiGraph()
        else:
            G = nx.Graph()
        for x, y, cost in self.edges2:
            G.add_edge(x + self.decrement, y + self.decrement, weight=cost)

        edge_labels = {(i, j): w['weight'] for i, j, w in G.edges(data=True)}
        pos = nx.spring_layout(G)
        nx.draw_networkx(G, pos, with_labels=True)
        nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
        plt.axis("off")
        plt.show()





N, M, P = map(int, input().split())
graph = Graph(N, directed=True, decrement=True)
for _ in range(M):
    x, y, cost = map(int, input().split())
    graph.add_edge(x, y, P-cost)

res = graph.bellman_ford2(1,N)
if res is None:
    print(-1)
else:
    print(max(-res,0))

Solution (Python):
import sys
input = sys.stdin.readline


class Graph:
    class Edge:
        def __init__(self, to, cost):
            """
            :param to:  終点ノード
            :param cost: 辺の重み
            """
            self.to, self.cost = to, cost

    def __init__(self, n, directed=False, decrement=True, edges=[]):
        self.n = n
        self.directed = directed
        self.decrement = decrement
        self.edges2 = []
        self.parent = [-1]*self.n
        self.info = [-1]*self.n
        for x, y, cost in edges:
            self.add_edge(x, y, cost)

    def add_edge(self, x, y, cost):
        if self.decrement:
            x -= 1
            y -= 1
        self.edges2.append((x, y, cost))
        if self.directed == False:
            self.edges2.append((y, x, cost))

    def bellman_ford(self, start, INF=10**18):
        """
        :return: 負の閉路が存在する場合は -1 を返す
        """
        dist = [INF] * self.n
        if self.decrement:
            start -= 1
        dist[start] = 0
        for cnt in range(self.n):
            for x, y, cost in self.edges2:
                if dist[x] != INF and dist[x] + cost < dist[y]:
                    if cnt == self.n - 1:
                        return -1
                    dist[y] = dist[x] + cost
        return dist

    def bellman_ford2(self, start, goal, INF=10**18):
        """
        :return: 負の閉路が存在する場合は -1 を返す
        """
        dist = [INF] * self.n
        if self.decrement:
            start -= 1
            goal -= 1
        dist[start] = 0
        for cnt in range(2*self.n):
            for x, y, cost in self.edges2:
                if dist[x] != INF and dist[x] + cost < dist[y]:
                    dist[y] = dist[x] + cost
                    if cnt >= self.n:
                        dist[y] = -INF
                if cnt == self.n - 1:
                    res = dist[goal]
        if res == dist[goal]:
            return res

    def draw(self):
        """
        :return: グラフを可視化
        """
        import matplotlib.pyplot as plt
        import networkx as nx

        if self.directed:
            G = nx.DiGraph()
        else:
            G = nx.Graph()
        for x, y, cost in self.edges2:
            G.add_edge(x + self.decrement, y + self.decrement, weight=cost)

        edge_labels = {(i, j): w['weight'] for i, j, w in G.edges(data=True)}
        pos = nx.spring_layout(G)
        nx.draw_networkx(G, pos, with_labels=True)
        nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
        plt.axis("off")
        plt.show()





N, M, P = map(int, input().split())
graph = Graph(N, directed=True, decrement=True)
for _ in range(M):
    x, y, cost = map(int, input().split())
    graph.add_edge(x, y, P-cost)

res = graph.bellman_ford2(1,N)
if res is None:
    print(-1)
else:
    print(max(-graph.bellman_ford2(1,N),0))

Solution (Python):
def getN():
    return int(input())
def getNM():
    return map(int, input().split())
def getList():
    return list(map(int, input().split()))
def getArray(intn):
    return [int(input()) for i in range(intn)]
def input():
    return sys.stdin.readline().rstrip()
def rand_N(ran1, ran2):
    return random.randint(ran1, ran2)
def rand_List(ran1, ran2, rantime):
    return [random.randint(ran1, ran2) for i in range(rantime)]
def rand_ints_nodup(ran1, ran2, rantime):
  ns = []
  while len(ns) < rantime:
    n = random.randint(ran1, ran2)
    if not n in ns:
      ns.append(n)
  return sorted(ns)

def rand_query(ran1, ran2, rantime):
  r_query = []
  while len(r_query) < rantime:
    n_q = rand_ints_nodup(ran1, ran2, 2)
    if not n_q in r_query:
      r_query.append(n_q)
  return sorted(r_query)

from collections import defaultdict, deque, Counter
from sys import exit
from decimal import *
import heapq
import math
from fractions import gcd
import random
import string
import copy
from itertools import combinations, permutations, product
from operator import mul, itemgetter
from functools import reduce
from bisect import bisect_left, bisect_right

import sys
sys.setrecursionlimit(1000000000)
mod = 10 ** 9 + 7





N, M, P = getNM()
que = [getList() for i in range(M)]

edges = []
for a, b, c in que:
    
    
    edges.append([a - 1, b - 1, c - P])













def bellman(edges, num_v):
    dist = [-float('inf') for i in range(num_v)]
    dist[0] = 0

    
    for i in range(N - 1):
        for edge in edges:
            if dist[edge[1]] < dist[edge[0]] + edge[2]:
                dist[edge[1]] = dist[edge[0]] + edge[2]

    
    nega = [0] * N
    for i in range(N):
        for edge in edges:
            
            
            if nega[edge[0]] == 1:
                nega[edge[1]] = 1
            if dist[edge[1]] < dist[edge[0]] + edge[2]:
                dist[edge[1]] = dist[edge[0]] + edge[2]
                nega[edge[1]] = 1

    if nega[N - 1]:
        print('-1')
        exit()

    return dist

ans = bellman(edges, N)[N - 1]
if ans <= 0:
    print(0)
else:
    print(ans)

Solution (Python):
import sys
sys.setrecursionlimit(10**7) 
import math
from copy import copy, deepcopy
from copy import deepcopy as dcp
from operator import itemgetter
from bisect import bisect_left, bisect, bisect_right

from collections import deque, defaultdict


from collections import Counter

from itertools import accumulate,combinations,permutations,product

from heapq import heapify,heappop,heappush

from functools import reduce,lru_cache

from decimal import Decimal

def input(): 
    x=sys.stdin.readline()
    return x[:-1] if x[-1]=="\n" else x
def printe(*x):print("
def printl(li): _=print(*li, sep="\n") if li else None
def argsort(s, return_sorted=False): 
    inds=sorted(range(len(s)), key=lambda k: s[k])
    if return_sorted: return inds, [s[i] for i in inds]
    return inds
def alp2num(c,cap=False): return ord(c)-97 if not cap else ord(c)-65
def num2alp(i,cap=False): return chr(i+97) if not cap else chr(i+65)
def matmat(A,B):
    K,N,M=len(B),len(A),len(B[0])
    return [[sum([(A[i][k]*B[k][j]) for k in range(K)]) for j in range(M)] for i in range(N)]
def matvec(M,v):
    N,size=len(v),len(M)
    return [sum([M[i][j]*v[j] for j in range(N)]) for i in range(size)]
def T(M):
    n,m=len(M),len(M[0])
    return [[M[j][i] for j in range(n)] for i in range(m)]
def binr(x): return bin(x)[2:]
def bitcount(x): 
    x= x - ((x >> 1) & 0x5555555555555555)
    x= (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333)
    x= (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f 
    x+= (x >> 8); x+= (x >> 16); x+= (x >> 32) 
    return x & 0x7f

def main():
    mod = 1000000007
    

    
    N, M,P = map(int, input().split())
    
    
    
    edge = [[] for i in range(N)]
    for i in range(M):
        a,b,w = map(int,input().split())
        edge[a-1].append((P-w,b-1))

    start=0
    inf=10**14
    d=[inf]*N
    d[start]=0
    for _ in range(N):
        update=False
        for e in range(N):
            for nd,ne in edge[e]:
                x=d[e]+nd
                if x<d[ne] and d[e]!=inf:
                    d[ne]=x
                    update=True
        if update==False: break
    printe(d[-1])
    for _ in range(N):
        update=False
        for e in range(N):
            for nd,ne in edge[e]:
                
                x=d[e]+nd
                if x<d[ne] and d[e]!=inf:
                    d[ne]=-inf
                    update=True
        if update==False: break
    
    if d[-1]==-inf:
        print(-1)
        return

    print(max(0,-d[N-1]))




if __name__ == "__main__":
    main()

Solution (Python):

from collections import deque

N, M, P = map(int, input().split())
X = [list(map(int, input().split())) for _ in range(M)]

to = [False] * (N + 1)
to[1] = True
q = deque([1])
while q:
    u = q.popleft()
    for a, b, c in X:
        if a == u and not to[b]:
            to[b] = True
            q.append(b)

ot = [False] * (N + 1)
ot[N] = True
q = deque([N])
while q:
    u = q.popleft()
    for a, b, c in X:
        if b == u and not ot[a]:
            ot[a] = True
            q.append(a)

INF = 10 ** 9 + 7
start = 1
d = [INF] * (N + 1)
d[start] = 0
updated = True
cnt = 0

while updated and cnt <= M:
    updated = False
    cnt += 1
    for u, v, c in X:
        if not to[u] or not ot[u] or not to[v] or not ot[v]:
            continue

        if d[v] > d[u] - (c - P):
            d[v] = d[u] - (c - P)
            updated = True

if cnt > N:
    print(-1)
else:
    print(max(0, -d[-1]))

Solution (Python):
import sys

input=sys.stdin.buffer.readline





def RD(): return sys.stdin.read()


def II(): return int(input())


def MI(): return map(int,input().split())


def MF(): return map(float,input().split())


def LI(): return list(map(int,input().split()))


def LF(): return list(map(float,input().split()))


def TI(): return tuple(map(int,input().split()))





def main():
	n,m,p=MI()
	G=[[] for _ in range(n+1)]
	
	for _ in range(m):
		a,b,c=MI()
		G[a].append([b,c-p])
	
	
	coin=[-10**18]*(n+1)
	coin[1]=0
	
	for _ in range(n):
		for i in range(1,n+1):
			for b,c in G[i]:
				coin[b]=max(coin[b],coin[i]+c)
	
	ans=coin[-1]
	
	check=[False]*(n+1)
	for i in range(1,n+1):
		for b,c in G[i]:
			if coin[b]<coin[i]+c and coin[b]>-10**10:
				check[b]=True
	
	for _ in range(n):
		for i in range(1,n+1):
			for b,c in G[i]:
				check[b]=check[i] or check[b]
	
	
	if check[n]==True:
		ans=-1
	else:
		ans=max(ans,0)
	
	print(ans)
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

if __name__=="__main__":
	main()