Problem:
Single Source Shortest Path (Negative Edges)
Input
An edge-weighted graph
G
(
V
,
E
) and the source
r
.
|
V
| |
E
|
r
s
0
t
0
d
0
s
1
t
1
d
1
:
s
|E|-1
t
|E|-1
d
|E|-1
|V|
is the number of vertices and
|E|
is the number of edges in
G
. The graph vertices are named with the numbers 0, 1,...,
|V|-1
respectively.
r
is the source of the graph.
s
i
and
t
i
represent source and target vertices of
i
-th edge (directed) and
d
i
represents the cost of the
i
-th edge.
Output
If the graph contains a negative cycle (a cycle whose sum of edge costs is a negative value) which is reachable from the source
r
, print
NEGATIVE CYCLE
in a line.
Otherwise, print
c
0
c
1
:
c
|V|-1
The output consists of
|V|
lines. Print the cost of the shortest path from the source
r
to each vertex 0, 1, ...
|V|-1
in order. If there is no path from the source to a vertex, print "
INF
".
Constraints
1 ≤
|V|
≤ 1000
0 ≤
|E|
≤ 2000
-10000 ≤
d
i
≤ 10000
There are no parallel edges
There are no self-loops
Sample Input 1
4 5 0
0 1 2
0 2 3
1 2 -5
1 3 1
2 3 2
Sample Output 1
0
2
-3
-1
Sample Input 2
4 6 0
0 1 2
0 2 3
1 2 -5
1 3 1
2 3 2
3 1 0
Sample Output 2
NEGATIVE CYCLE
Sample Input 3
4 5 1
0 1 2
0 2 3
1 2 -5
1 3 1
2 3 2
Sample Output 3
INF
0
-5
-3

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<ll, ll> P;

int main() {
    ll n, m, s;
    cin >> n >> m >> s;

    const ll INF = 8e18;
    vector<vector<ll>> dist(n,vector<ll>(n,INF));
    for (ll i = 0; i < n; i++) dist[i][i] = 0;

    vector<vector<P>> graph(n);
    for (ll i = 0; i < m; i++) {
        ll a, b, d;
        cin >> a >> b >> d;
        graph[a].emplace_back(b, d);
        dist[a][b] = min(dist[a][b], d);
    }

    for (ll k = 0; k < n; k++) {
        for (ll i = 0; i < n; i++) {
            for (ll j = 0; j < n; j++) {
                if (dist[i][k] == INF || dist[k][j] == INF) continue;
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }

    vector<bool> visited(n,false);
    auto dfs = [&](auto dfs, ll x) -> void {
        visited[x] = true;
        for (auto edge : graph[x]) {
            ll nex = edge.first;
            ll cost = edge.second;

            if (visited[nex]) continue;
            dfs(dfs, nex);
        }
    };

    dfs(dfs, s);
    for (int i = 0; i < n; i++) {
        if (!visited[i]) continue;
        if (dist[i][i] < 0) {
            cout << "NEGATIVE CYCLE" << endl;
            return 0;
        }
    }


    for (ll j = 0; j < n; j++) {
        if (dist[s][j] == INF) {
            cout << "INF" << endl;
        } else {
            cout << dist[s][j] << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 11264
final_rank: 8

code_snippet: #include <bits/stdc++.h>


using namespace std;
//make -f ../makefile SRC=
/*
*/


//------------------------------------------------------------------------------
bool DEBUG = false;
const int INF = 2147483647;

const int MAX_N = 1000;
static int G[MAX_N][MAX_N];
static int D[MAX_N];

//------------------------------------------------------------------------------
bool bellman_ford(int N, int src)
{
    //--------------------------------------------------------------------------
    // init params:
    for (int n=0; n<N; ++n) D[n] = INF;
    D[src] = 0;

    //--------------------------------------------------------------------------
    // do this N times:
    for (int unused=0; unused<N-1; ++unused)
    {
        // for each edge:
        for (int v=0; v<N; ++v)
        {
            if (D[v] == INF) continue;
            for (int w=0; w<N; ++w)
            {
                if (w == v || G[v][w] == INF) continue;
                // relax the edge:
                if (D[w] == INF || D[w] > D[v]+G[v][w]) D[w] = D[v] + G[v][w];
            }
        }
    }

    if (DEBUG) {for (int v=0; v<N; ++v) if (D[v] != INF) printf("v=%d, D=%d\n", v, D[v]);}

    for (int v=0; v<N; ++v)
    {
        for (int w=0; w<N; ++w)
        {
            if (w == v || G[v][w] == INF) continue;
            if (D[v] == INF) continue;
            if (D[w] > D[v] + G[v][w])
            {
                return true;
            }
        }
    }
    return false;
}
//------------------------------------------------------------------------------
void floyd_warshall(int N)
{
    for (int k=0; k<N; k++)
    {
        for (int i=0; i<N; i++)
        {
            if (G[i][k] == INF) continue;
            for (int j=0; j<N; j++)
            {
                if (G[k][j] == INF) continue;
                if (G[i][j] == INF || G[i][j] > G[i][k] + G[k][j])
                    G[i][j] = G[i][k] + G[k][j];
            }
        }
    }
}

//------------------------------------------------------------------------------
void solve(int N, int src)
{
    //--------------------------------------------------------------------------
    // base cases:
    if (bellman_ford(N, src))
    {
        printf("NEGATIVE CYCLE\n");
        return;
    }
    //--------------------------------------------------------------------------
    // init:
    //--------------------------------------------------------------------------
    // compute:
    floyd_warshall(N);

    //--------------------------------------------------------------------------
    // report:
    for (int v=0; v<N; ++v)
    {
        if (G[src][v] == INF) printf("INF\n");
        else printf("%d\n", G[src][v]);
    }
}

//------------------------------------------------------------------------------
void test()
{

}

//------------------------------------------------------------------------------
int main()
{
    //test(); return 0;
    //DEBUG = true;
    //--------------------------------------------------------------------------
    int N, M, v, w, c, src, num;

    num = scanf("%d %d %d ", &N, &M, &src);
    for (int v=0; v<N; v++)
    {
        for (int w=0; w<N; w++)
        {
            if (v != w) G[v][w] = INF;
            else G[v][w] = 0;
        }
    }

    for (int m=0; m<M; ++m)
    {
        num = scanf("%d %d %d ", &v, &w, &c);
        G[v][w] = min(G[v][w], c);
    }
    solve(N, src);
    //--------------------------------------------------------------------------
    return 0;
}
//------------------------------------------------------------------------------
accuracy: 1
time_ms: 790
memory_kb: 7316
final_rank: 9

code_snippet: #include <bits/stdc++.h>


using namespace std;
//make -f ../makefile SRC=
/*
*/


//------------------------------------------------------------------------------
bool DEBUG = false;
const int INF = 2147483647;

const int MAX_N = 1000;
static int G[MAX_N][MAX_N];
static int D[MAX_N];

//------------------------------------------------------------------------------
bool bellman_ford(int N, int src)
{
    //--------------------------------------------------------------------------
    // init params:
    for (int n=0; n<=N; ++n) D[n] = INF;
    D[src] = 0;

    //--------------------------------------------------------------------------
    // do this N times:
    for (int unused=0; unused<N-1; ++unused)
    {
        // for each edge:
        for (int v=0; v<N; ++v)
        {
            if (D[v] == INF) continue;
            for (int w=0; w<N; ++w)
            {
                if (w == v || G[v][w] == INF) continue;
                // relax the edge:
                if (D[w] == INF || D[w] > D[v]+G[v][w]) D[w] = D[v] + G[v][w];
            }
        }
    }

    if (DEBUG) {for (int v=0; v<N; ++v) if (D[v] != INF) printf("v=%d, D=%d\n", v, D[v]);}

    for (int v=0; v<N; ++v)
    {
        for (int w=0; w<N; ++w)
        {
            if (w == v || G[v][w] == INF) continue;
            if (D[v] == INF) continue;
            if (D[w] > D[v] + G[v][w])
            {
                return true;
            }
        }
    }
    return false;
}
//------------------------------------------------------------------------------
void floyd_warshall(int N)
{
    for (int k=0; k<N; k++)
    {
        for (int i=0; i<N; i++)
        {
            if (G[i][k] == INF) continue;
            for (int j=0; j<N; j++)
            {
                if (G[k][j] == INF) continue;
                if (G[i][j] == INF || G[i][j] > G[i][k] + G[k][j])
                    G[i][j] = G[i][k] + G[k][j];
            }
        }
    }
}

//------------------------------------------------------------------------------
void solve(int N, int src)
{
    //--------------------------------------------------------------------------
    // base cases:
    if (bellman_ford(N, src))
    {
        printf("NEGATIVE CYCLE\n");
        return;
    }
    //--------------------------------------------------------------------------
    // init:
    //--------------------------------------------------------------------------
    // compute:
    floyd_warshall(N);

    //--------------------------------------------------------------------------
    // report:
    for (int v=0; v<N; ++v)
    {
        if (G[src][v] == INF) printf("INF\n");
        else printf("%d\n", G[src][v]);
    }
}

//------------------------------------------------------------------------------
void test()
{

}

//------------------------------------------------------------------------------
int main()
{
    //test(); return 0;
    //DEBUG = true;
    //--------------------------------------------------------------------------
    int N, M, v, w, c, src, num;

    num = scanf("%d %d %d ", &N, &M, &src);
    for (int v=0; v<N; v++)
    {
        for (int w=0; w<N; w++)
        {
            if (v != w) G[v][w] = INF;
            else G[v][w] = 0;
        }
    }

    for (int m=0; m<M; ++m)
    {
        num = scanf("%d %d %d ", &v, &w, &c);
        G[v][w] = min(G[v][w], c);
    }
    solve(N, src);
    //--------------------------------------------------------------------------
    return 0;
}
//------------------------------------------------------------------------------
accuracy: 0.975
time_ms: 790
memory_kb: 7448
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(n);++i)
using namespace std;
using ll = long long;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n,m,s;
    cin >> n >> m >> s;

    vector<vector<int>> es(m);
    rep(i,m){
        int a,b,c;
        cin >> a >> b >> c;
        es[i] = {a,b,c};
    } 

    vector<ll> dist(n,1e18);
    dist[s] = 0;


    rep(_,n-1){
        for(auto e:es){
            if(dist[e[0]]!=1e18 && dist[e[1]]>dist[e[0]]+e[2]){
                dist[e[1]] = dist[e[0]]+e[2];
            }
        }
    }
    rep(_,n-1){
        for(auto e: es){
            if(dist[e[0]]!=1e18 && dist[e[1]]>dist[e[0]]+e[2]){
                cout << "NEGATIVE CYCLE" << endl;
                return 0;
            }
        }
    }

    rep(i,n) {
        if(dist[i]==1e18) cout << "INF" << endl;
        else cout << dist[i] << endl;
    }

}
accuracy: 1
time_ms: 50
memory_kb: 3464
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define vi vector<int64_t>
#define vvi vector<vi>
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
int main(){
   ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int64_t v,e,r,sum=0;
    cin>>v>>e>>r;
    vector<vvi> a(v,vvi(0,vi(2)));
    vi kiro(v,INT_MAX);
    rep(i,e){
      int s,t,d;
      cin>>s>>t>>d;
      a[s].push_back({t,d});
    }
    queue<int> tan,sak;
    rep(i,a[r].size()){
      tan.push(r);
    }
    kiro[r]=0;
    while(tan.size()>0){
      if(sum>e*v)break;
      //cout<<"ya";
      int sou=tan.front();
      tan.pop();
      rep(i,a[sou].size()){
        if(kiro[a[sou][i][0]]>kiro[sou]+a[sou][i][1]){
          kiro[a[sou][i][0]]=kiro[sou]+a[sou][i][1];
          //cout<<kiro[a[sou][i][0]]<<" "<<sou<<"  ";
          tan.push(a[sou][i][0]);
          sum++;
        }
      }
    }
    if(sum>e*v){
      cout<<"NEGATIVE CYCLE"<<endl;
      return 0;
    }
    rep(i,v){
      if(kiro[i]!=INT_MAX){
        cout<<kiro[i]<<endl;
      }
      else cout<<"INF"<<endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3560
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(a) (a).begin(), (a).end()
#define pb push_back
#define fi first
#define se second
mt19937_64 rng(chrono::system_clock::now().time_since_epoch().count());
const ll MOD1000000007 = 1000000007;
const ll MOD998244353 = 998244353;
const ll MOD[3] = {999727999, 1070777777, 1000000007};
const ll LINF = 1LL << 60LL;
const int IINF = (1 << 30) - 2;


template<typename T> 
struct edge{
    int from;
    int to;
    T cost;
    int id;

    edge(){}
    edge(int to, T cost=1) : from(-1), to(to), cost(cost){}
    edge(int to, T cost, int id) : from(-1), to(to), cost(cost), id(id){}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id){}

    void reverse(){swap(from, to);}
};

template<typename T>
struct edges : std::vector<edge<T>>{
    void sort(){
        std::sort(
            (*this).begin(),
            (*this).end(), 
            [](const edge<T>& a, const edge<T>& b){
                return a.cost < b.cost;
            }
        );
    }
};

template<typename T = bool>
struct graph : std::vector<edges<T>>{
private:
    int n = 0;
    int m = 0;
    edges<T> es;
    bool dir;

public:
    graph(int n, bool dir) : n(n), dir(dir){
        (*this).resize(n);
    }

    void add_edge(int from, int to, T cost=1){
        if(dir){
            es.push_back(edge<T>(from, to, cost, m));
            (*this)[from].push_back(edge<T>(from, to, cost, m++));
        }else{
            if(from > to) swap(from, to);
            es.push_back(edge<T>(from, to, cost, m));
            (*this)[from].push_back(edge<T>(from, to, cost, m));
            (*this)[to].push_back(edge<T>(to, from, cost, m++));
        }
    }

    int get_vnum(){
        return n;
    }

    int get_enum(){
        return m;
    }

    bool get_dir(){
        return dir;
    }

    edge<T> get_edge(int i){
        return es[i];
    }

    edges<T> get_edge_set(){
        return es;
    }
};

template<typename T>
struct redge{
    int from, to;
    T cap, cost;
    int rev;
    
    redge(int to, T cap, T cost=(T)(1)) : from(-1), to(to), cap(cap), cost(cost){}
    redge(int to, T cap, T cost, int rev) : from(-1), to(to), cap(cap), cost(cost), rev(rev){}
};

template<typename T> using Edges = vector<edge<T>>;
template<typename T> using weighted_graph = vector<Edges<T>>;
template<typename T> using tree = vector<Edges<T>>;
using unweighted_graph = vector<vector<int>>;
template<typename T> using residual_graph = vector<vector<redge<T>>>;


class shortest_path{
public:
    template<typename T>
    static vector<T> dijkstra(graph<T> &G, int s){
        int n = G.get_vnum();
        const T TINF = numeric_limits<T>::max()/2;
        vector<T> dist(n, TINF);

        dist[s] = 0;
        priority_queue<pair<T, int>, vector<pair<T, int>>, greater<>> que;
        que.push({0, s});
        while(!que.empty()){
            auto [d, v] = que.top();
            que.pop();
            if(dist[v] < d) continue;

            for(auto e : G[v]){
                if(dist[v] + e.cost < dist[e.to]){
                    dist[e.to] = dist[v] + e.cost;
                    que.push({dist[e.to], e.to});
                }
            }
        }

        for(int v=0; v<n; v++) if(dist[v]==TINF) dist[v] = -1;

        return dist;
    }
    
    template<typename T>
    static vector<T> bellmanford(graph<T> &G, int s){
        int n = G.get_vnum();
        bool dir = G.get_dir();
        const T TINF = numeric_limits<T>::max()/2;
        edges<T> es = G.get_edge_set();
        vector<T> dist(n, TINF);
        vector<bool> flag(n, false);

        dist[s] = 0;
        for(int i=0; i<n; i++) for(auto e : es){
            if(dist[e.from]!=TINF && dist[e.from]+e.cost<dist[e.to]) dist[e.to] = dist[e.from] + e.cost;
            if(!dir && dist[e.to]!=TINF && dist[e.to]+e.cost<dist[e.from]) dist[e.from] = dist[e.to] + e.cost;
        }

        for(int i=0; i<n; i++) for(auto e : es){
            if(dist[e.from]!=TINF && dist[e.from]+e.cost<dist[e.to]) dist[e.to] = dist[e.from] + e.cost, flag[e.to]=true;
            if(!dir && dist[e.to]!=TINF && dist[e.to]+e.cost<dist[e.from]) dist[e.from] = dist[e.to] + e.cost, flag[e.from]=true;
        }

        for(int i=0; i<n; i++) for(auto e : es){
            flag[e.to] = flag[e.to] | flag[e.from];
            if(!dir) flag[e.from] = flag[e.from] | flag[e.to];
        }
        for(int v=0; v<n; v++) if(flag[v]) dist[v] = -TINF;

        return dist;
    }

    template<typename T>
    vector<vector<T>> warshall_floyd(graph<T> &G){
        int n = G.get_vnum();
        const T TINF = numeric_limits<T>::max()/2;
        vector<vector<T>> dist(n, vector<T>(n, TINF));
        
        for(int v=0; v<n; v++) for(auto e : G[v]) dist[v][e.to] = min(dist[v][e.to], e.cost);
        for(int k=0; k<n; k++) for(int i=0; i<n; i++) for(int j=0; j<n; j++) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

        return dist;
    }

    template<typename T>
    vector<T> yen(graph<T> &G, int s, int t, int k){
        
    }
};


void solve(){
    int n, m, s; cin >> n >> m >> s;
    graph<int> G(n, true);
    for(int i=0; i<m; i++){
        int u, v, w; cin >> u >> v >> w;
        G.add_edge(u, v, w);
    }

    auto dist = shortest_path::bellmanford<int>(G, s);
    for(int v=0; v<n; v++) if(dist[v] <= -IINF){
        cout << "NEGATIVE CYCLE\n";
        return;
    }
    for(int v=0; v<n; v++){
        if(IINF <= dist[v]) cout << "INF\n";
        else cout << dist[v] << '\n';
    }
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    
    int T=1;
    //cin >> T;
    while(T--) solve();
}
accuracy: 1
time_ms: 10
memory_kb: 3500
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<vvb> vvvb;
typedef vector<vvvb> vvvvb;
typedef pair<ll,ll> pi;
typedef pair<ll,pi> ppi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define sz(A) (ll)(A.size())
#define ALL(A) A.begin(),A.end()
#define LB(A,x) (ll)(lower_bound(ALL(A),x)-A.begin())
#define UB(A,x) (ll)(upper_bound(ALL(A),x)-A.begin())
#define COU(A,x) (UB(A,x)-LB(A,x))
#define F first
#define S second
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.F<<" "<<p.S;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.F>>p.S;return is;}
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){REP(i,sz(v))os<<v[i]<<(i+1!=sz(v)?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<class T>bool chmax(T&a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T>bool chmin(T&a,T b){if(b<a){a=b;return 1;}return 0;}
const ll mod=998244353;
int main(){
  ll N,M,r;cin>>N>>M>>r;
  vector<vector<pi>>E(N);
  REP(i,M){
    ll u,v,d;cin>>u>>v>>d;
    E[u].emplace_back(pi(v,d));
  }
  vi D(N,1e18);
  D[r]=0;
  min_priority_queue<pi>Q;
  Q.emplace(pi(0,r));
  while(sz(Q)){
    ll d=Q.top().F,v=Q.top().S;Q.pop();
    if(d!=D[v])continue;
    if(clock()>0.5*CLOCKS_PER_SEC){cout<<"NEGATIVE CYCLE"<<endl;return 0;}
    for(auto[u,c]:E[v])if(chmin(D[u],d+c)){
      Q.emplace(pi(d+c,u));
    }
  }
  REP(i,N){
    if(D[i]>1e17)cout<<"INF"<<endl;
    else cout<<D[i]<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 490
memory_kb: 70716
final_rank: 10

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
#define rep(i, n) for(int i = 0;i < (int)(n); i ++)
#define REP(i, j, n) for (int i = (int)(j); i < (int)(n) ; i ++)
using namespace std;
//using namespace atcoder;
// atcoder::dsu uf(N);のように使う
//コンパイルは下記のmain.cppをコンパイルしたいファイル名に書き換える
//g++ main.cpp -std=c++14 -I .  
//閉路の個数はleader[i] == iでfor文して数える。
//連結成分のノード数もsizeで検出可能 

typedef long long ll;
const ll LINF = numeric_limits<long long>::max();
template <typename T>
bool chmax(T &a,const T &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <typename T>
bool chmin(T &a,const T &b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <typename T>
void print_map(const map<T, T> &dict) {
    for (auto itr = dict.begin();itr != dict.end(); itr++ ) {
        cout << itr->first << ": " << itr->second << endl;
    }
}
template <typename T>
void print_set(const set<T> &ssss) {
    cout << "set content: " ;
    for (auto itt = ssss.begin(); itt != ssss.end() ; itt++) {
        cout << *itt << " " ;
    }
    cout << endl;
}
ll power(ll radix, ll index2) {
    ll ans = 1;
    if (index2 == 0) return 1;
    while (index2 >= 1)
    {
        /* code */
        ans *= radix;
        index2 -= 1;
    }
    return ans;
}
ll stol2 (string num) {
    ll ans = 0;
    rep(i, num.size()) {
        ans += (num[i] - '0') * power(10, num.size() - i -1);
    }
    return ans;
}
ll gcd(ll m , ll n) {
    if (n == 0) return m;
    return gcd(n, m % n);
}
//二分探索で[50,50,50,51]のような同じものが複数個
//あるようなとき左と右どちらに合わせるかで注意!!
int main() {
    ll n, m ; cin >> n >> m;
    ll r ; cin >> r;
    map<pair<ll,ll>, ll> weight;
    vector<pair<ll,ll>> edge;
    if (n == 1) {
        cout << 0 << endl;
        exit(0);
    }
    rep(i, m) {
        ll v,v2, w; cin >> v >> v2 >> w;
        edge.push_back(make_pair(v, v2));
        weight[make_pair(v,v2)] = w;
    }
    vector<ll> dist(n, 100100100100);
    dist[r] = 0;
    int t = 1;
    ll count = 0;
    while ((t == 1) && (count <= n-1))
    {
        /* code */
        t = 0;
        rep(i, m) {
            ll now_node = edge[i].first;
            ll next_node = edge[i].second;
            ll cost = weight[make_pair(now_node, next_node)];
            //cout << cost << endl;
            if (dist[now_node] == 100100100100) continue;
            if (dist[now_node] + cost < dist[next_node]) {
                //cout << "i; " << i << " now_node: " << now_node << " next_node: " << next_node << endl; 
                dist[next_node] = dist[now_node] +cost;
                t = 1;
            }
        } 
        if (t) {
            count ++;
            if (count == n) {
                cout << "NEGATIVE CYCLE" << endl;
                exit(0);
            }
        }
    }
    rep(i, n) {
        if (dist[i] >= 10010010010) cout << "INF" << endl;
        else cout << dist[i] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3508
final_rank: 4

code_snippet: #ifdef DEBUG
  #define _GLIBCXX_DEBUG
  #define REPEAT_MAIN( BOUND ) START_MAIN; signal( SIGABRT , &AlertAbort ); AutoCheck( exec_mode , use_getline ); if( exec_mode == sample_debug_mode || exec_mode == submission_debug_mode || exec_mode == library_search_mode ){ return 0; } else if( exec_mode == experiment_mode ){ Experiment(); return 0; } else if( exec_mode == small_test_mode ){ SmallTest(); return 0; }; DEXPR( int , bound_test_case_num , BOUND , min( BOUND , 100 ) ); int test_case_num = 1; if( exec_mode == solve_mode ){ if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } } else if( exec_mode == random_test_mode ){ CERR( "ランダムテストを行う回数を指定してください。" ); SET_LL( test_case_num ); } FINISH_MAIN
  #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , DEBUG_VALUE )
  #define ASSERT( A , MIN , MAX ) CERR( "ASSERTチェック： " , ( MIN ) , ( ( MIN ) <= A ? "<=" : ">" ) , A , ( A <= ( MAX ) ? "<=" : ">" ) , ( MAX ) ); assert( ( MIN ) <= A && A <= ( MAX ) )
  #define SET_ASSERT( A , MIN , MAX ) if( exec_mode == solve_mode ){ SET_LL( A ); ASSERT( A , MIN , MAX ); } else if( exec_mode == random_test_mode ){ CERR( #A , " = " , ( A = GetRand( MIN , MAX ) ) ); } else { assert( false ); }
  #define SOLVE_ONLY static_assert( __FUNCTION__[0] == 'S' )
  #define CERR( ... ) VariadicCout( cerr , __VA_ARGS__ ) << endl
  #define COUT( ... ) VariadicCout( cout << "出力： " , __VA_ARGS__ ) << endl
  #define CERR_A( A , N ) OUTPUT_ARRAY( cerr , A , N ) << endl
  #define COUT_A( A , N ) cout << "出力： "; OUTPUT_ARRAY( cout , A , N ) << endl
  #define CERR_ITR( A ) OUTPUT_ITR( cerr , A ) << endl
  #define COUT_ITR( A ) cout << "出力： "; OUTPUT_ITR( cout , A ) << endl
#else
  #pragma GCC optimize ( "O3" )
  #pragma GCC optimize ( "unroll-loops" )
  #pragma GCC target ( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" )
  #define REPEAT_MAIN( BOUND ) START_MAIN; CEXPR( int , bound_test_case_num , BOUND ); int test_case_num = 1; if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } FINISH_MAIN
  #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , VALUE )
  #define ASSERT( A , MIN , MAX ) assert( ( MIN ) <= A && A <= ( MAX ) )
  #define SET_ASSERT( A , MIN , MAX ) SET_LL( A ); ASSERT( A , MIN , MAX )
  #define SOLVE_ONLY 
  #define CERR( ... ) 
  #define COUT( ... ) VariadicCout( cout , __VA_ARGS__ ) << ENDL
  #define CERR_A( A , N ) 
  #define COUT_A( A , N ) OUTPUT_ARRAY( cout , A , N ) << ENDL
  #define CERR_ITR( A ) 
  #define COUT_ITR( A ) OUTPUT_ITR( cout , A ) << ENDL
#endif
#ifdef REACTIVE
  #define ENDL endl
#else
  #define ENDL "\n"
#endif
#ifdef USE_GETLINE
  #define SET_LL( A ) { GETLINE( A ## _str ); A = stoll( A ## _str ); }
  #define GETLINE_SEPARATE( SEPARATOR , ... ) SOLVE_ONLY; string __VA_ARGS__; VariadicGetline( cin , SEPARATOR , __VA_ARGS__ )
  #define GETLINE( ... ) SOLVE_ONLY; GETLINE_SEPARATE( '\n' , __VA_ARGS__ )
#else
  #define SET_LL( A ) cin >> A
  #define CIN( LL , ... ) SOLVE_ONLY; LL __VA_ARGS__; VariadicCin( cin , __VA_ARGS__ )
  #define SET_A( A , N ) SOLVE_ONLY; FOR( VARIABLE_FOR_CIN_A , 0 , N ){ cin >> A[VARIABLE_FOR_CIN_A]; }
  #define CIN_A( LL , A , N ) vector<LL> A( N ); SET_A( A , N );
#endif
#include <bits/stdc++.h>
using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using lld = __float128;
template <typename INT> using T2 = pair<INT,INT>;
template <typename INT> using T3 = tuple<INT,INT,INT>;
template <typename INT> using T4 = tuple<INT,INT,INT,INT>;
using path = pair<int,ll>;
#define ATT __attribute__( ( target( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" ) ) )
#define START_MAIN int main(){ ios_base::sync_with_stdio( false ); cin.tie( nullptr )
#define FINISH_MAIN REPEAT( test_case_num ){ if constexpr( bound_test_case_num > 1 ){ CERR( "testcase " , VARIABLE_FOR_REPEAT_test_case_num , ":" ); } Solve(); CERR( "" ); } }
#define START_WATCH chrono::system_clock::time_point watch = chrono::system_clock::now()
#define CURRENT_TIME static_cast<double>( chrono::duration_cast<chrono::microseconds>( chrono::system_clock::now() - watch ).count() / 1000.0 )
#define CHECK_WATCH( TL_MS ) ( CURRENT_TIME < TL_MS - 100.0 )
#define TYPE_OF( VAR ) decay_t<decltype( VAR )>
#define CEXPR( LL , BOUND , VALUE ) constexpr LL BOUND = VALUE
#define CIN_ASSERT( A , MIN , MAX ) TYPE_OF( MAX ) A; SET_ASSERT( A , MIN , MAX )
#define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( TYPE_OF( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ )
#define FOREQ( VAR , INITIAL , FINAL ) for( TYPE_OF( FINAL ) VAR = INITIAL ; VAR <= FINAL ; VAR ++ )
#define FOREQINV( VAR , INITIAL , FINAL ) for( TYPE_OF( INITIAL ) VAR = INITIAL ; VAR + 1 > FINAL ; VAR -- )
#define AUTO_ITR( ARRAY ) auto itr_ ## ARRAY = ARRAY .begin() , end_ ## ARRAY = ARRAY .end()
#define FOR_ITR( ARRAY ) for( AUTO_ITR( ARRAY ) , itr = itr_ ## ARRAY ; itr_ ## ARRAY != end_ ## ARRAY ; itr_ ## ARRAY ++ , itr++ )
#define REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT_ ## HOW_MANY_TIMES , 0 , HOW_MANY_TIMES )
#define SET_PRECISION( DECIMAL_DIGITS ) cout << fixed << setprecision( DECIMAL_DIGITS )
#define OUTPUT_ARRAY( OS , A , N ) FOR( VARIABLE_FOR_OUTPUT_ARRAY , 0 , N ){ OS << A[VARIABLE_FOR_OUTPUT_ARRAY] << (VARIABLE_FOR_OUTPUT_ARRAY==N-1?"":" "); } OS
#define OUTPUT_ITR( OS , A ) { auto ITERATOR_FOR_OUTPUT_ITR = A.begin() , END_FOR_OUTPUT_ITR = A.end(); bool VARIABLE_FOR_OUTPUT_ITR = ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR; while( VARIABLE_FOR_OUTPUT_ITR ){ OS << *ITERATOR_FOR_COUT_ITR; ( VARIABLE_FOR_OUTPUT_ITR = ++ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR ) ? OS : OS << " "; } } OS
#define RETURN( ... ) SOLVE_ONLY; COUT( __VA_ARGS__ ); return
#define COMPARE( ... ) auto naive = Naive( __VA_ARGS__ ); auto answer = Answer( __VA_ARGS__ ); bool match = naive == answer; COUT( "(" , #__VA_ARGS__ , ") == (" , __VA_ARGS__ , ") : Naive == " , naive , match ? "==" : "!=" , answer , "== Answer" ); if( !match ){ return; }

// 入出力用
template <class Traits> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is ) { return is; }
template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is , Arg& arg , ARGS&... args ) { return VariadicCin( is >> arg , args... ); }
template <class Traits> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator ) { return is; }
template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator , Arg& arg , ARGS&... args ) { return VariadicGetline( getline( is , arg , separator ) , separator , args... ); }
template <class Traits , typename Arg> inline basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os , const vector<Arg>& arg ) { auto begin = arg.begin() , end = arg.end(); auto itr = begin; while( itr != end ){ ( itr == begin ? os : os << " " ) << *itr; itr++; } return os; }
template <class Traits , typename Arg> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg& arg ) { return os << arg; }
template <class Traits , typename Arg1 , typename Arg2 , typename... ARGS> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg1& arg1 , const Arg2& arg2 , const ARGS&... args ) { return VariadicCout( os << arg1 << " " , arg2 , args... ); }

// デバッグ用
#ifdef DEBUG
  inline void AlertAbort( int n ) { CERR( "abort関数が呼ばれました。assertマクロのメッセージが出力されていない場合はオーバーフローの有無を確認をしてください。" ); }
  void AutoCheck( int& exec_mode , const bool& use_getline );
  inline void Solve();
  inline void Experiment();
  inline void SmallTest();
  inline void RandomTest();
  ll GetRand( const ll& Rand_min , const ll& Rand_max );
  int exec_mode;
  CEXPR( int , solve_mode , 0 );
  CEXPR( int , sample_debug_mode , 1 );
  CEXPR( int , submission_debug_mode , 2 );
  CEXPR( int , library_search_mode , 3 );
  CEXPR( int , experiment_mode , 4 );
  CEXPR( int , small_test_mode , 5 );
  CEXPR( int , random_test_mode , 6 );
  #ifdef USE_GETLINE
    CEXPR( bool , use_getline , true );
  #else
    CEXPR( bool , use_getline , false );
  #endif
#else
  ll GetRand( const ll& Rand_min , const ll& Rand_max ) { ll answer = time( NULL ); return answer * rand() % ( Rand_max + 1 - Rand_min ) + Rand_min; }
#endif

// 圧縮用
#define TE template
#define TY typename
#define US using
#define ST static
#define IN inline
#define CL class
#define PU public
#define OP operator
#define CE constexpr
#define CO const
#define NE noexcept
#define RE return 
#define WH while
#define VO void
#define VE vector
#define LI list
#define BE begin
#define EN end
#define SZ size
#define MO move
#define TH this
#define CRI CO int&
#define CRUI CO uint&
#define CRL CO ll&

// VVV 常設ライブラリは以下に挿入する。
// Map
// c:/Users/user/Documents/Programming/Mathematics/Function/Map
CL is_ordered{PU:is_ordered()= delete;TE <TY T> ST CE auto Check(CO T& t)-> decltype(t < t,true_type());ST CE false_type Check(...);TE <TY T> ST CE CO bool value = is_same_v< decltype(Check(declval<T>())),true_type >;};
TE <TY T , TY U>US Map = conditional_t<is_constructible_v<unordered_map<T,int>>,unordered_map<T,U>,conditional_t<is_ordered::value<T>,map<T,U>,void>>;
// AAA 常設ライブラリは以上に挿入する。

// グラフ用
template <typename PATH> vector<list<PATH> > gE;
template <typename T , template <typename...> typename V> inline auto Get( const V<T>& a ) { return [&]( const int& i ){ return a[i]; }; }


// 圧縮時は中身だけ削除する。
inline void Experiment()
{
}

// 圧縮時は中身だけ削除する。
inline void SmallTest()
{
}

// VVV 常設でないライブラリは以下に挿入する。

template <typename U>
class VirtualPointedSet
{

public:
  virtual const U& Point() const noexcept = 0;
  inline const U& Unit() const noexcept;
  inline const U& Zero() const noexcept;
  inline const U& One() const noexcept;
  inline const U& Infty() const noexcept;
  inline const U& size() const noexcept;

};

template <typename U>
class PointedSet :
  virtual public VirtualPointedSet<U>
{

private:
  U m_b_U;

public:
  inline PointedSet( const U& b_u = U() );
  inline const U& Point() const noexcept;

};

template <typename U>
class VirtualNSet
{

public:
  virtual U Transfer( const U& u ) = 0;
  inline U Inverse( const U& u );

};

template <typename U , typename F_U>
class AbstractNSet :
  virtual public VirtualNSet<U>
{

private:
  F_U m_f_U;

public:
  inline AbstractNSet( F_U f_U );
  inline U Transfer( const U& u );

};

template <typename U>
class VirtualMagma
{

public:
  virtual U Product( const U& u0 , const U& u1 ) = 0;
  inline U Sum( const U& u0 , const U& u1 );

};

template <typename U , typename M_U>
class AbstractMagma :
  virtual public VirtualMagma<U>
{

private:
  M_U m_m_U;

public:
  inline AbstractMagma( M_U m_U );
  inline U Product( const U& u0 , const U& u1 );

};

template <typename U> inline PointedSet<U>::PointedSet( const U& b_U ) : m_b_U( b_U ) {}
template <typename U> inline const U& PointedSet<U>::Point() const noexcept { return m_b_U; }
template <typename U> inline const U& VirtualPointedSet<U>::Unit() const noexcept { return Point(); }
template <typename U> inline const U& VirtualPointedSet<U>::Zero() const noexcept { return Point(); }
template <typename U> inline const U& VirtualPointedSet<U>::One() const noexcept { return Point(); }
template <typename U> inline const U& VirtualPointedSet<U>::Infty() const noexcept { return Point(); }
template <typename U> inline const U& VirtualPointedSet<U>::size() const noexcept { return Point(); }

template <typename U , typename F_U> inline AbstractNSet<U,F_U>::AbstractNSet( F_U f_U ) : m_f_U( move( f_U ) ) { static_assert( is_invocable_r_v<U,F_U,U> ); }
template <typename U , typename F_U> inline U AbstractNSet<U,F_U>::Transfer( const U& u ) { return m_f_U( u ); }
template <typename U> inline U VirtualNSet<U>::Inverse( const U& u ) { return Transfer( u ); }

template <typename U , typename M_U> inline AbstractMagma<U,M_U>::AbstractMagma( M_U m_U ) : m_m_U( move( m_U ) ) { static_assert( is_invocable_r_v<U,M_U,U,U> ); }
template <typename U , typename M_U> inline U AbstractMagma<U,M_U>::Product( const U& u0 , const U& u1 ) { return m_m_U( u0 , u1 ); }
template <typename U> inline U VirtualMagma<U>::Sum( const U& u0 , const U& u1 ) { return Product( u0 , u1 ); }


template <typename U>
class VirtualMonoid :
  virtual public VirtualMagma<U> ,
  virtual public VirtualPointedSet<U>
{};

template <typename U = ll>
class AdditiveMonoid :
  virtual public VirtualMonoid<U> ,
  public PointedSet<U>
{

public:
  inline U Product( const U& u0 , const U& u1 );
  static inline AdditiveMonoid<U>& Object();

};

template <typename U = ll>
class MultiplicativeMonoid :
  virtual public VirtualMonoid<U> ,
  public PointedSet<U>
{

public:
  inline MultiplicativeMonoid( const U& e_U );
  inline U Product( const U& u0 , const U& u1 );
  static inline MultiplicativeMonoid<U>& Object();

};

template <typename U , typename M_U>
class AbstractMonoid :
  virtual public VirtualMonoid<U> ,
  public AbstractMagma<U,M_U> ,
  public PointedSet<U>
{

public:
  inline AbstractMonoid( M_U m_U , const U& e_U );
  inline U Product( const U& u0 , const U& u1 );

};

template <typename U> inline MultiplicativeMonoid<U>::MultiplicativeMonoid( const U& e_U ) : PointedSet<U>( e_U ) {}
template <typename U , typename M_U> inline AbstractMonoid<U,M_U>::AbstractMonoid( M_U m_U , const U& e_U ) : AbstractMagma<U,M_U>( move( m_U ) ) , PointedSet<U>( e_U ) {}

template <typename U> inline U AdditiveMonoid<U>::Product( const U& u0 , const U& u1 ) { return u0 + u1; }
template <typename U> inline U MultiplicativeMonoid<U>::Product( const U& u0 , const U& u1 ) { return u0 * u1; }
template <typename U , typename M_U> inline U AbstractMonoid<U,M_U>::Product( const U& u0 , const U& u1 ) { return m_m_U( u0 , u1 ); }

template <typename U> inline AdditiveMonoid<U>& AdditiveMonoid<U>::Object() { static AdditiveMonoid<U> obj{}; return obj; }


#ifndef RET_TYPE
  #define RET_TYPE
  template <typename F , typename...Args> using ret_t = decltype( declval<F>()( declval<Args>()... ) );
#endif
#ifndef INNER_TYPE
  #define INNER_TYPE
  template <typename T> using inner_t = typename T::type;
#endif
#ifndef decldecay_t
  #define decldecay_t( VAR ) decay_t<decltype( VAR )>
#endif

// Enumeration:N->R1-->TとEnumeration_inv:T->R2-->Nは互いに逆写像である仮想関数。
template <typename T , typename R1 , typename R2 , typename E>
class VirtualGraph :
  public PointedSet<int>
{

private:
  E m_edge;

public:
  inline VirtualGraph( const int& size , E edge );
  virtual R1 Enumeration( const int& i ) = 0;
  virtual R2 Enumeration_inv( const T& t ) = 0;
  inline void Reset();
  ret_t<E,T> Edge( const T& t );
  using type = T;

};

template <typename E>
class Graph :
  virtual public VirtualGraph<int,const int&,const int&,E>
{
  
public:
  inline Graph( const int& size , E edge );
  inline const int& Enumeration( const int& i );
  inline const int& Enumeration_inv( const int& t );
  template <typename F> inline Graph<F> GetGraph( F edge ) const;

};

template <typename T , typename Enum_T , typename Enum_T_inv , typename E>
class EnumerationGraph :
  virtual public VirtualGraph<T,ret_t<Enum_T,int>,ret_t<Enum_T_inv,T>,E>
{

private:
  Enum_T m_enum_T;
  Enum_T_inv m_enum_T_inv;
  
public:
  inline EnumerationGraph( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge );
  inline ret_t<Enum_T,int> Enumeration( const int& i );
  inline ret_t<Enum_T_inv,T> Enumeration_inv( const T& t );
  template <typename F> inline EnumerationGraph<T,Enum_T,Enum_T_inv,F> GetGraph( F edge ) const;

};
template <typename Enum_T , typename Enum_T_inv , typename E> EnumerationGraph( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge ) -> EnumerationGraph<decldecay_t(get<0>(declval<E>()(0).front())),Enum_T,Enum_T_inv,E>;

// 推論補助のためにE::operator()はデフォルト引数が必要。
template <typename T , typename E>
class MemorisationGraph :
  virtual public VirtualGraph<T,T,const int&,E>
{

private:
  int m_length;
  vector<T> m_memory;
  Map<T,int> m_memory_inv;
  
public:
  inline MemorisationGraph( const int& size , E edge );
  // push_backする可能性のあるvectorなので参照にしないように注意
  inline T Enumeration( const int& i );
  inline const int& Enumeration_inv( const T& t );
  inline void Reset();
  template <typename F> inline MemorisationGraph<T,F> GetGraph( F edge ) const;

};
template <typename E> MemorisationGraph( const int& size , E edge ) -> MemorisationGraph<decldecay_t(get<0>(declval<E>()().front())),E>;

template <typename T , typename R1 , typename R2 , typename E> inline VirtualGraph<T,R1,R2,E>::VirtualGraph( const int& size , E edge ) : PointedSet<int>( size ) , m_edge( move( edge ) ) { static_assert( is_constructible_v<T,R1> && is_constructible_v<int,R2> && is_invocable_v<E,T> ); }
template <typename E> inline Graph<E>::Graph( const int& size , E edge ) : VirtualGraph<int,const int&,const int&,E>( size , move( edge ) ) {}
template <typename T , typename Enum_T , typename Enum_T_inv , typename E> inline EnumerationGraph<T,Enum_T,Enum_T_inv,E>::EnumerationGraph( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge ) : VirtualGraph<T,ret_t<Enum_T,int>,ret_t<Enum_T_inv,T>,E>( size , move( edge ) ) , m_enum_T( move( enum_T ) ) , m_enum_T_inv( move( enum_T_inv ) ) {}
template <typename T , typename E> inline MemorisationGraph<T,E>::MemorisationGraph( const int& size , E edge ) : VirtualGraph<T,T,const int&,E>( size , move( edge ) ) , m_length() , m_memory() , m_memory_inv() {}

template <typename T , typename R1 , typename R2 , typename E> inline ret_t<E,T> VirtualGraph<T,R1,R2,E>::Edge( const T& t ) { return m_edge( t ); }

template <typename E> inline const int& Graph<E>::Enumeration( const int& i ) { return i; }
template <typename T , typename Enum_T , typename Enum_T_inv , typename E> inline ret_t<Enum_T,int> EnumerationGraph<T,Enum_T,Enum_T_inv,E>::Enumeration( const int& i ) { return m_enum_T( i ); }
template <typename T , typename E> inline T MemorisationGraph<T,E>::Enumeration( const int& i ) { assert( 0 <= i && i < m_length ); return m_memory[i]; }

template <typename E> inline const int& Graph<E>::Enumeration_inv( const int& i ) { return i; }
template <typename T , typename Enum_T , typename Enum_T_inv , typename E> inline ret_t<Enum_T_inv,T> EnumerationGraph<T,Enum_T,Enum_T_inv,E>::Enumeration_inv( const T& t ) { return m_enum_T_inv( t ); }
template <typename T , typename E> inline const int& MemorisationGraph<T,E>::Enumeration_inv( const T& t )
{

  if( m_memory_inv.count( t ) == 0 ){

    assert( m_length < this->size() );
    m_memory.push_back( t );
    return m_memory_inv[t] = m_length++;

  }
  
  return m_memory_inv[t];

}

template <typename T , typename R1 , typename R2 , typename E> void VirtualGraph<T,R1,R2,E>::Reset() {}
template <typename T , typename E> inline void MemorisationGraph<T,E>::Reset() { m_length = 0; m_memory.clear(); m_memory_inv.clear(); }

template <typename E> template <typename F> inline Graph<F> Graph<E>::GetGraph( F edge ) const { return Graph<F>( this->size() , move( edge ) ); }
template <typename T , typename Enum_T , typename Enum_T_inv , typename E> template <typename F> inline EnumerationGraph<T,Enum_T,Enum_T_inv,F> EnumerationGraph<T,Enum_T,Enum_T_inv,E>::GetGraph( F edge ) const { return EnumerationGraph( this->size() , m_enum_T , m_enum_T_inv , move( edge ) ); }
template <typename T , typename E> template <typename F> inline MemorisationGraph<T,F> MemorisationGraph<T,E>::GetGraph( F edge ) const { return MemorisationGraph( this->size() , move( edge ) ); }

#define BELLMAN_FORD_BODY( INITIALISE_PREV , SET_PREV )			\
  const U& zero = m_M.Zero();						\
  const U& infty = this->Infty();					\
  assert( zero < infty );						\
  const int& size = m_G.size();						\
  auto&& i_start = m_G.Enumeration_inv( t_start );			\
  assert( 0 <= i_start && i_start < size );				\
  vector<bool> found( size );						\
  vector<U> weight( size , infty );					\
  found[i_start] = true;						\
  weight[i_start] = 0;							\
  INITIALISE_PREV;							\
									\
  for( int length = 0 ; length < size ; length++ ){			\
  									\
    for( int i = 0 ; i < size ; i++ ){					\
									\
      if( found[i] ){							\
									\
	const U& weight_i = weight[i];					\
	assert( weight_i != infty );					\
	auto&& edge_i = m_G.Edge( m_G.Enumeration( i ) );		\
									\
	for( auto itr = edge_i.begin() , end = edge_i.end() ; itr != end ; itr++ ){ \
									\
	  auto&& j = m_G.Enumeration_inv( itr->first );			\
	  const U& edge_ij = itr->second;				\
	  U temp = m_M.Sum( weight_i , edge_ij );			\
	  U& weight_j = weight[j];					\
									\
	  if( weight_j > temp ){					\
									\
	    found[j] = true;						\
	    weight_j = move( temp );					\
	    SET_PREV;							\
									\
	  }								\
									\
	}								\
									\
      }									\
									\
    }									\
									\
  }									\
									\
  bool valid = true;							\
									\
  for( int i = 0 ; i < size && valid ; i++ ){				\
									\
    if( found[i] ){							\
									\
      const U& weight_i = weight[i];					\
      auto&& edge_i = m_G.Edge( m_G.Enumeration( i ) );			\
									\
      for( auto itr = edge_i.begin() , end = edge_i.end() ; itr != end ; itr++ ){ \
									\
	auto&& j = m_G.Enumeration_inv( itr->first );			\
	const U& edge_ij = itr->second;					\
	U& weight_j = weight[j];					\
	const U temp = m_M.Sum( weight_i , edge_ij );			\
									\
	if( weight_j > temp ){						\
									\
	  valid = false;						\
	  break;							\
									\
	}								\
									\
      }									\
									\
    }									\
									\
  }									\


// GRAPHはグラフG=(V_G,E_G:T->(T \times U)^{< \omega})に相当する型。

// 入力の範囲内で要件
// (0) Mは全順序可換モノイド構造である。
// (1) inftyがE_Gの値の各成分の第2成分|V_G|個以下の和で表せるいかなる数よりも大きい。
// が成り立つ場合にのみサポート。

// 単一始点全終点最短経路探索／経路復元なしO(|V_G| |E_G|)
// 単一始点全終点最短経路探索／経路復元ありO(|V_G| |E_G|)
template <typename GRAPH , typename MONOID , typename U>
class AbstractBellmanFord :
  public PointedSet<U>
{

private:
  GRAPH m_G;
  MONOID m_M;

public:
  inline AbstractBellmanFord( GRAPH G , MONOID M , const U& infty );

  // 負の閉路が存在すればfalse、存在しなければtrueを第1成分に返す。
  tuple<bool,vector<U>> GetDistance( const inner_t<GRAPH>& t_start );
  tuple<bool,vector<U>,vector<list<inner_t<GRAPH>>>> GetPath( const inner_t<GRAPH>& t_start );
  
};

template <typename GRAPH>
class BellmanFord :
  public AbstractBellmanFord<GRAPH,AdditiveMonoid<>,ll>
{

public:
  inline BellmanFord( GRAPH G );
  
};

template <typename GRAPH , typename MONOID , typename U> inline AbstractBellmanFord<GRAPH,MONOID,U>::AbstractBellmanFord( GRAPH G , MONOID M , const U& infty ) : PointedSet<U>( infty ) , m_G( move( G ) ) , m_M( move( M ) ) { static_assert( ! is_same_v<U,int> ); }

template <typename GRAPH> inline BellmanFord<GRAPH>::BellmanFord( GRAPH G ) : AbstractBellmanFord<GRAPH,AdditiveMonoid<>,ll>( move( G ) , AdditiveMonoid<>::Object() , 4611686018427387904 ) {}

template <typename GRAPH , typename MONOID , typename U>
tuple<bool,vector<U>> AbstractBellmanFord<GRAPH,MONOID,U>::GetDistance( const inner_t<GRAPH>& t_start )
{

  BELLMAN_FORD_BODY( , );
  m_G.Reset();
  return { valid , move( weight ) };

}

template <typename GRAPH , typename MONOID , typename U>
tuple<bool,vector<U>,vector<list<inner_t<GRAPH>>>> AbstractBellmanFord<GRAPH,MONOID,U>::GetPath( const inner_t<GRAPH>& t_start )
{

  BELLMAN_FORD_BODY( vector<int> prev( size ) , prev[j] = i );
  vector<list<inner_t<GRAPH>>> path( valid ? size : 0 );

  if( valid ){
    
    for( int j = 0 ; j < size ; j++ ){

      auto& path_j = path[j];
      int i = j;

      while( i != i_start ){

	path_j.push_front( m_G.Enumeration( i ) );
	i = prev[i];

      }

      path_j.push_front( t_start );

    }

  }

  m_G.Reset();
  return { valid , move( weight ) , move( path ) };

}

// AAA 常設でないライブラリは以上に挿入する。

inline void Solve()
{
  CIN( int , N , M , r );
  gE<path>.resize( N );
  FOR( j , 0 , M ){
    CIN( int , uj , vj );
    CIN( ll , wj );
    gE<path>[uj].push_back( { vj , wj } );
  }
  Graph graph{ N , Get( gE<path> ) };
  BellmanFord bf{ move( graph ) };
  auto [b,weight] = bf.GetDistance( r );
  if( b ){
    FOR( i , 0 , N ){
      if( weight[i] == bf.Infty() ){
	COUT( "INF" );
      } else {
	COUT( weight[i] );
      }
    }
  } else {
    COUT( "NEGATIVE CYCLE" );
  }
}
REPEAT_MAIN(1);
accuracy: 1
time_ms: 30
memory_kb: 3592
final_rank: 6

code_snippet: #ifdef DEBUG
  #define _GLIBCXX_DEBUG
  #define REPEAT_MAIN( BOUND ) START_MAIN; signal( SIGABRT , &AlertAbort ); AutoCheck( exec_mode , use_getline ); if( exec_mode == sample_debug_mode || exec_mode == submission_debug_mode || exec_mode == library_search_mode ){ return 0; } else if( exec_mode == experiment_mode ){ Experiment(); return 0; } else if( exec_mode == small_test_mode ){ SmallTest(); return 0; }; DEXPR( int , bound_test_case_num , BOUND , min( BOUND , 100 ) ); int test_case_num = 1; if( exec_mode == solve_mode ){ if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } } else if( exec_mode == random_test_mode ){ CERR( "ランダムテストを行う回数を指定してください。" ); SET_LL( test_case_num ); } FINISH_MAIN
  #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , DEBUG_VALUE )
  #define ASSERT( A , MIN , MAX ) CERR( "ASSERTチェック： " , ( MIN ) , ( ( MIN ) <= A ? "<=" : ">" ) , A , ( A <= ( MAX ) ? "<=" : ">" ) , ( MAX ) ); assert( ( MIN ) <= A && A <= ( MAX ) )
  #define SET_ASSERT( A , MIN , MAX ) if( exec_mode == solve_mode ){ SET_LL( A ); ASSERT( A , MIN , MAX ); } else if( exec_mode == random_test_mode ){ CERR( #A , " = " , ( A = GetRand( MIN , MAX ) ) ); } else { assert( false ); }
  #define SOLVE_ONLY static_assert( __FUNCTION__[0] == 'S' )
  #define CERR( ... ) VariadicCout( cerr , __VA_ARGS__ ) << endl
  #define COUT( ... ) VariadicCout( cout << "出力： " , __VA_ARGS__ ) << endl
  #define CERR_A( A , N ) OUTPUT_ARRAY( cerr , A , N ) << endl
  #define COUT_A( A , N ) cout << "出力： "; OUTPUT_ARRAY( cout , A , N ) << endl
  #define CERR_ITR( A ) OUTPUT_ITR( cerr , A ) << endl
  #define COUT_ITR( A ) cout << "出力： "; OUTPUT_ITR( cout , A ) << endl
#else
  #pragma GCC optimize ( "O3" )
  #pragma GCC optimize ( "unroll-loops" )
  #pragma GCC target ( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" )
  #define REPEAT_MAIN( BOUND ) START_MAIN; CEXPR( int , bound_test_case_num , BOUND ); int test_case_num = 1; if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } FINISH_MAIN
  #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , VALUE )
  #define ASSERT( A , MIN , MAX ) assert( ( MIN ) <= A && A <= ( MAX ) )
  #define SET_ASSERT( A , MIN , MAX ) SET_LL( A ); ASSERT( A , MIN , MAX )
  #define SOLVE_ONLY 
  #define CERR( ... ) 
  #define COUT( ... ) VariadicCout( cout , __VA_ARGS__ ) << ENDL
  #define CERR_A( A , N ) 
  #define COUT_A( A , N ) OUTPUT_ARRAY( cout , A , N ) << ENDL
  #define CERR_ITR( A ) 
  #define COUT_ITR( A ) OUTPUT_ITR( cout , A ) << ENDL
#endif
#ifdef REACTIVE
  #define ENDL endl
#else
  #define ENDL "\n"
#endif
#ifdef USE_GETLINE
  #define SET_LL( A ) { GETLINE( A ## _str ); A = stoll( A ## _str ); }
  #define GETLINE_SEPARATE( SEPARATOR , ... ) SOLVE_ONLY; string __VA_ARGS__; VariadicGetline( cin , SEPARATOR , __VA_ARGS__ )
  #define GETLINE( ... ) SOLVE_ONLY; GETLINE_SEPARATE( '\n' , __VA_ARGS__ )
#else
  #define SET_LL( A ) cin >> A
  #define CIN( LL , ... ) SOLVE_ONLY; LL __VA_ARGS__; VariadicCin( cin , __VA_ARGS__ )
  #define SET_A( A , N ) SOLVE_ONLY; FOR( VARIABLE_FOR_CIN_A , 0 , N ){ cin >> A[VARIABLE_FOR_CIN_A]; }
  #define CIN_A( LL , A , N ) vector<LL> A( N ); SET_A( A , N );
#endif
#include <bits/stdc++.h>
using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using lld = __float128;
template <typename INT> using T2 = pair<INT,INT>;
template <typename INT> using T3 = tuple<INT,INT,INT>;
template <typename INT> using T4 = tuple<INT,INT,INT,INT>;
using path = pair<int,ll>;
#define ATT __attribute__( ( target( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" ) ) )
#define START_MAIN int main(){ ios_base::sync_with_stdio( false ); cin.tie( nullptr )
#define FINISH_MAIN REPEAT( test_case_num ){ if constexpr( bound_test_case_num > 1 ){ CERR( "testcase " , VARIABLE_FOR_REPEAT_test_case_num , ":" ); } Solve(); CERR( "" ); } }
#define START_WATCH chrono::system_clock::time_point watch = chrono::system_clock::now()
#define CURRENT_TIME static_cast<double>( chrono::duration_cast<chrono::microseconds>( chrono::system_clock::now() - watch ).count() / 1000.0 )
#define CHECK_WATCH( TL_MS ) ( CURRENT_TIME < TL_MS - 100.0 )
#define TYPE_OF( VAR ) decay_t<decltype( VAR )>
#define CEXPR( LL , BOUND , VALUE ) constexpr LL BOUND = VALUE
#define CIN_ASSERT( A , MIN , MAX ) TYPE_OF( MAX ) A; SET_ASSERT( A , MIN , MAX )
#define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( TYPE_OF( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ )
#define FOREQ( VAR , INITIAL , FINAL ) for( TYPE_OF( FINAL ) VAR = INITIAL ; VAR <= FINAL ; VAR ++ )
#define FOREQINV( VAR , INITIAL , FINAL ) for( TYPE_OF( INITIAL ) VAR = INITIAL ; VAR + 1 > FINAL ; VAR -- )
#define AUTO_ITR( ARRAY ) auto itr_ ## ARRAY = ARRAY .begin() , end_ ## ARRAY = ARRAY .end()
#define FOR_ITR( ARRAY ) for( AUTO_ITR( ARRAY ) , itr = itr_ ## ARRAY ; itr_ ## ARRAY != end_ ## ARRAY ; itr_ ## ARRAY ++ , itr++ )
#define REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT_ ## HOW_MANY_TIMES , 0 , HOW_MANY_TIMES )
#define SET_PRECISION( DECIMAL_DIGITS ) cout << fixed << setprecision( DECIMAL_DIGITS )
#define OUTPUT_ARRAY( OS , A , N ) FOR( VARIABLE_FOR_OUTPUT_ARRAY , 0 , N ){ OS << A[VARIABLE_FOR_OUTPUT_ARRAY] << (VARIABLE_FOR_OUTPUT_ARRAY==N-1?"":" "); } OS
#define OUTPUT_ITR( OS , A ) { auto ITERATOR_FOR_OUTPUT_ITR = A.begin() , END_FOR_OUTPUT_ITR = A.end(); bool VARIABLE_FOR_OUTPUT_ITR = ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR; while( VARIABLE_FOR_OUTPUT_ITR ){ OS << *ITERATOR_FOR_COUT_ITR; ( VARIABLE_FOR_OUTPUT_ITR = ++ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR ) ? OS : OS << " "; } } OS
#define RETURN( ... ) SOLVE_ONLY; COUT( __VA_ARGS__ ); return
#define COMPARE( ... ) auto naive = Naive( __VA_ARGS__ ); auto answer = Answer( __VA_ARGS__ ); bool match = naive == answer; COUT( "(" , #__VA_ARGS__ , ") == (" , __VA_ARGS__ , ") : Naive == " , naive , match ? "==" : "!=" , answer , "== Answer" ); if( !match ){ return; }

// 入出力用
template <class Traits> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is ) { return is; }
template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is , Arg& arg , ARGS&... args ) { return VariadicCin( is >> arg , args... ); }
template <class Traits> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator ) { return is; }
template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator , Arg& arg , ARGS&... args ) { return VariadicGetline( getline( is , arg , separator ) , separator , args... ); }
template <class Traits , typename Arg> inline basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os , const vector<Arg>& arg ) { auto begin = arg.begin() , end = arg.end(); auto itr = begin; while( itr != end ){ ( itr == begin ? os : os << " " ) << *itr; itr++; } return os; }
template <class Traits , typename Arg> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg& arg ) { return os << arg; }
template <class Traits , typename Arg1 , typename Arg2 , typename... ARGS> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg1& arg1 , const Arg2& arg2 , const ARGS&... args ) { return VariadicCout( os << arg1 << " " , arg2 , args... ); }

// デバッグ用
#ifdef DEBUG
  inline void AlertAbort( int n ) { CERR( "abort関数が呼ばれました。assertマクロのメッセージが出力されていない場合はオーバーフローの有無を確認をしてください。" ); }
  void AutoCheck( int& exec_mode , const bool& use_getline );
  inline void Solve();
  inline void Experiment();
  inline void SmallTest();
  inline void RandomTest();
  ll GetRand( const ll& Rand_min , const ll& Rand_max );
  int exec_mode;
  CEXPR( int , solve_mode , 0 );
  CEXPR( int , sample_debug_mode , 1 );
  CEXPR( int , submission_debug_mode , 2 );
  CEXPR( int , library_search_mode , 3 );
  CEXPR( int , experiment_mode , 4 );
  CEXPR( int , small_test_mode , 5 );
  CEXPR( int , random_test_mode , 6 );
  #ifdef USE_GETLINE
    CEXPR( bool , use_getline , true );
  #else
    CEXPR( bool , use_getline , false );
  #endif
#else
  ll GetRand( const ll& Rand_min , const ll& Rand_max ) { ll answer = time( NULL ); return answer * rand() % ( Rand_max + 1 - Rand_min ) + Rand_min; }
#endif

// 圧縮用
#define TE template
#define TY typename
#define US using
#define ST static
#define IN inline
#define CL class
#define PU public
#define OP operator
#define CE constexpr
#define CO const
#define NE noexcept
#define RE return 
#define WH while
#define VO void
#define VE vector
#define LI list
#define BE begin
#define EN end
#define SZ size
#define MO move
#define TH this
#define CRI CO int&
#define CRUI CO uint&
#define CRL CO ll&

// VVV 常設ライブラリは以下に挿入する。
// Map
// c:/Users/user/Documents/Programming/Mathematics/Function/Map
CL is_ordered{PU:is_ordered()= delete;TE <TY T> ST CE auto Check(CO T& t)-> decltype(t < t,true_type());ST CE false_type Check(...);TE <TY T> ST CE CO bool value = is_same_v< decltype(Check(declval<T>())),true_type >;};
TE <TY T , TY U>US Map = conditional_t<is_constructible_v<unordered_map<T,int>>,unordered_map<T,U>,conditional_t<is_ordered::value<T>,map<T,U>,void>>;
// AAA 常設ライブラリは以上に挿入する。

// グラフ用
template <typename PATH> vector<list<PATH> > gE;
template <typename T , template <typename...> typename V> inline auto Get( const V<T>& a ) { return [&]( const int& i ){ return a[i]; }; }


// 圧縮時は中身だけ削除する。
inline void Experiment()
{
}

// 圧縮時は中身だけ削除する。
inline void SmallTest()
{
}

// VVV 常設でないライブラリは以下に挿入する。

template <typename U>
class VirtualMonoid
{

public:
  virtual U Product( const U& u0 , const U& u1 ) = 0;
  virtual const U& Unit() = 0;

};

// 加法モノイド
template <typename U = ll>
class Monoid :
  virtual public VirtualMonoid<U>
{

public:
  inline U Product( const U& u0 , const U& u1 );
  inline const U& Unit();

  static inline Monoid<U>& Object();

};

template <typename U , typename M_U , typename E_U>
class AbstractMonoid :
  virtual public VirtualMonoid<U>
{

private:
  M_U m_m_U;
  E_U m_e_U;

public:
  inline AbstractMonoid( M_U m_U , E_U e_U );

  inline U Product( const U& u0 , const U& u1 );
  inline const U& Unit();

};

template <typename U , typename M_U , typename E_U> inline AbstractMonoid<U,M_U,E_U>::AbstractMonoid( M_U m_U , E_U e_U ) : VirtualMonoid<U>() , m_m_U( m_U ) , m_e_U( e_U ) { static_assert( is_invocable_r_v<U,M_U,U,U> && is_invocable_r_v<const U&,E_U> ); }

template <typename U> inline U Monoid<U>::Product( const U& u0 , const U& u1 ) { return u0 + u1; }
template <typename U , typename M_U , typename E_U> inline U AbstractMonoid<U,M_U,E_U>::Product( const U& u0 , const U& u1 ) { return m_e_U( u0 , u1 ); }

template <typename U> inline const U& Monoid<U>::Unit() { static const U zero{}; return zero; }
template <typename U , typename M_U , typename E_U> inline const U& AbstractMonoid<U,M_U,E_U>::Unit() { return m_e_U(); }

template <typename U> inline Monoid<U>& Monoid<U>::Object() { static Monoid<U> obj{}; return obj; }


// Eは写像edge:T->(T \times ...)^{< omega}に相当するデータ。
// Enumeration:N->R1-->TとEnumeration_inv:T->R2-->Nは互いに逆写像である仮想関数。
template <typename T , typename R1 , typename R2 , typename E>
class VirtualGraph
{

protected:
  int m_size;
  E m_edge;

public:
  inline VirtualGraph( const int& size , E edge );

  inline const int& size() const noexcept;
  inline decltype(declval<E>()(declval<T>())) Edge( const T& );

  virtual R1 Enumeration( const int& i ) = 0;
  virtual R2 Enumeration_inv( const T& t ) = 0;
  virtual void Reset();

};

// 入力の範囲内で条件
// (1) Enumeration:N->R1-->TとEnumeration_inv:T->R2-->Nが全単射。
// を満たす場合にのみサポート。
template <typename E>
class Graph :
  virtual public VirtualGraph<int,const int&,const int&,E>
{
  
public:
  inline Graph( const int& V , E edge );

  inline const int& Enumeration( const int& i );
  inline const int& Enumeration_inv( const int& t );

};

template <typename T , typename R1 , typename Enum_T , typename R2 , typename Enum_T_inv , typename E>
class EnumerationGraph :
  virtual public VirtualGraph<T,R1,R2,E>
{

private:
  Enum_T m_enum_T;
  Enum_T_inv m_enum_T_inv;
  
public:
  inline EnumerationGraph( const int& V , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge );

  inline R1 Enumeration( const int& i );
  inline R2 Enumeration_inv( const T& t );

};
template <typename Enum_T , typename Enum_T_inv , typename E> EnumerationGraph( const int& V , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge ) -> EnumerationGraph<decay_t<decltype(declval<Enum_T>()(0))>,decltype(declval<Enum_T>()(0)),Enum_T,decltype(declval<Enum_T_inv>()(declval<decay_t<decltype(declval<Enum_T>()(0))>>())),Enum_T_inv,E>;

template <typename T , typename E>
class MemorisationGraph :
  virtual public VirtualGraph<T,T,const int&,E>
{

private:
  int m_length;
  vector<T> m_memory;
  Map<T,int> m_memory_inv;
  
public:
  inline MemorisationGraph( const int& V , E edge );

  // push_backする可能性のあるvectorなので参照にしないように注意
  inline T Enumeration( const int& i );
  inline const int& Enumeration_inv( const T& t );
  inline void Reset();

};

template <typename T , typename R1 , typename R2 , typename E> inline VirtualGraph<T,R1,R2,E>::VirtualGraph( const int& size , E edge ) : m_size( size ) , m_edge( move( edge ) ) { static_assert( is_invocable_v<E,T> && is_constructible_v<T,R1> && is_constructible_v<int,R2> ); }
template <typename E> inline Graph<E>::Graph( const int& V , E edge ) : VirtualGraph<int,const int&,const int&,E>( V , move( edge ) ) {}
template <typename T , typename R1 , typename Enum_T , typename R2 , typename Enum_T_inv , typename E> inline EnumerationGraph<T,R1,Enum_T,R2,Enum_T_inv,E>::EnumerationGraph( const int& V , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge ) : VirtualGraph<int,R1,R2,E>( V , move( edge ) ) , m_enum_T( move( enum_T ) ) , m_enum_T_inv( move( enum_T_inv ) ) { static_assert( is_same_v<R1,decltype(declval<Enum_T>()(0))> && is_same_v<R2,decltype(declval<Enum_T_inv>()(declval<T>()))> && is_same_v<T,decay_t<R1>> ); }
template <typename T , typename E> inline MemorisationGraph<T,E>::MemorisationGraph( const int& V , E edge ) : VirtualGraph<T,T,const int&,E>( V , move( edge ) ) , m_length() , m_memory() , m_memory_inv() {}

template <typename T , typename R1 , typename R2 , typename E> inline const int& VirtualGraph<T,R1,R2,E>::size() const noexcept { return m_size; }
template <typename T , typename R1 , typename R2 , typename E> inline decltype(declval<E>()(declval<T>())) VirtualGraph<T,R1,R2,E>::Edge( const T& t ) { return m_edge( t ); }

template <typename E> inline const int& Graph<E>::Enumeration( const int& i ) { return i; }
template <typename T , typename R1 , typename Enum_T , typename R2 , typename Enum_T_inv , typename E> inline R1 EnumerationGraph<T,R1,Enum_T,R2,Enum_T_inv,E>::Enumeration( const int& i ) { return m_enum_T( i ); }
template <typename T , typename E> inline T MemorisationGraph<T,E>::Enumeration( const int& i ) { assert( 0 <= i && i < m_length ); return m_memory[i]; }

template <typename E> inline const int& Graph<E>::Enumeration_inv( const int& i ) { return i; }
template <typename T , typename R1 , typename Enum_T , typename R2 , typename Enum_T_inv , typename E> inline R2 EnumerationGraph<T,R1,Enum_T,R2,Enum_T_inv,E>::Enumeration_inv( const T& t ) { return m_enum_T_inv( t ); }
template <typename T , typename E> inline const int& MemorisationGraph<T,E>::Enumeration_inv( const T& t )
{

  if( m_memory_inv.count( t ) == 0 ){

    assert( m_length < this->m_size );
    m_memory.push_back( t );
    return m_memory_inv[t] = m_length++;

  }
  
  return m_memory_inv[t];

}

template <typename T , typename R1 , typename R2 , typename E> void VirtualGraph<T,R1,R2,E>::Reset() {}
template <typename T , typename E> inline void MemorisationGraph<T,E>::Reset() { m_length = 0; m_memory.clear(); m_memory_inv.clear(); }


#define BELLMAN_FORD_BODY( INITIALISE_PREV , SET_PREV )			\
  const U& unit = m_p_M->Unit();					\
  assert( unit < m_infty );						\
  const int& size = m_p_G->size();					\
  auto&& i_start = m_p_G->Enumeration_inv( t_start );			\
  assert( 0 <= i_start && i_start < size );				\
  vector<bool> found( size );						\
  vector<U> weight( size , m_infty );					\
  found[i_start] = true;						\
  weight[i_start] = 0;							\
  INITIALISE_PREV;							\
									\
  for( int length = 0 ; length < size ; length++ ){			\
  									\
    for( int i = 0 ; i < size ; i++ ){				\
									\
      if( found[i] ){							\
									\
	const U& weight_i = weight[i];					\
	assert( weight_i != m_infty );					\
	auto&& edge_i = m_p_G->Edge( m_p_G->Enumeration( i ) );			\
									\
	for( auto itr_edge_i = edge_i.begin() , end_edge_i = edge_i.end() ; itr_edge_i != end_edge_i ; itr_edge_i++ ){ \
									\
	  auto&& j = m_p_G->Enumeration_inv( itr_edge_i->first );	\
	  const U& edge_ij = itr_edge_i->second;			\
	  U temp = m_p_M->Product( weight_i , edge_ij );		\
	  U& weight_j = weight[j];					\
									\
	  if( weight_j > temp ){					\
									\
	    found[j] = true;						\
	    weight_j = move( temp );					\
	    SET_PREV;							\
									\
	  }								\
									\
	}								\
									\
      }									\
									\
    }									\
									\
  }									\
									\
  bool valid = true;							\
									\
  for( int i = 0 ; i < size && valid ; i++ ){				\
									\
    if( found[i] ){							\
									\
      const U& weight_i = weight[i];					\
      auto&& edge_i = m_p_G->Edge( m_p_G->Enumeration( i ) ); \
									\
      for( auto itr_edge_i = edge_i.begin() , end_edge_i = edge_i.end() ; itr_edge_i != end_edge_i ; itr_edge_i++ ){ \
									\
	const int& j = m_p_G->Enumeration_inv( itr_edge_i->first );	\
	const U& edge_ij = itr_edge_i->second;				\
	U& weight_j = weight[j];					\
	const U temp = m_p_M->Product( weight_i , edge_ij );		\
									\
	if( weight_j > temp ){						\
									\
	  valid = false;						\
	  break;							\
									\
	}								\
									\
      }									\
									\
    }									\
									\
  }									\

// Eは写像edge:T->(T \times U)^{< \omega}に相当する型。
// メモリが不足する場合はEの定義を前計算しないでその都度計算させること。

// 入力の範囲内で要件
// (1) inftyがEの値の各成分の第2成分|V_G|個以下の和で表せるいかなる数よりも大きい。
// (2) Vの各要素u,vに対し、辺u->vが複数存在する場合は重みが最小のものが前にpushされている。
// が成り立つ場合にのみサポート。

// 単一始点全終点最短経路探索／経路復元なしO(size |edge|)
// 単一始点全終点最短経路探索／経路復元ありO(size |edge|)
template <typename T , typename U , typename R1 , typename R2 , typename E>
class AbstractBellmanFord
{

private:
  VirtualGraph<T,R1,R2,E>* m_p_G;
  VirtualMonoid<U>* m_p_M;
  U m_infty;

public:
  inline AbstractBellmanFord( VirtualGraph<T,R1,R2,E>& G , VirtualMonoid<U>& M , const U& infty );

  const U& Infty() const;
  
  // 負の閉路が存在すればfalse、存在しなければtrueを第1成分に返す。
  tuple<bool,vector<U>> GetDistance( const T& t_start );
  tuple<bool,vector<U>,vector<list<T>>> GetPath( const T& t_start );
  
};

template <typename T , typename R1 , typename R2 , typename E>
class BellmanFord :
  public AbstractBellmanFord<T,ll,R1,R2,E>
{

public:
  inline BellmanFord( VirtualGraph<T,R1,R2,E>& G );
  
};

template <typename T , typename U , typename R1 , typename R2 , typename E> inline AbstractBellmanFord<T,U,R1,R2,E>::AbstractBellmanFord( VirtualGraph<T,R1,R2,E>& G , VirtualMonoid<U>& M , const U& infty ) : m_p_G( &G ) , m_p_M( &M ) , m_infty( infty ) { static_assert( ! is_same_v<U,int> && is_invocable_r_v<list<pair<T,U>>,E,T> ); }
template <typename T , typename R1 , typename R2 , typename E> inline BellmanFord<T,R1,R2,E>::BellmanFord( VirtualGraph<T,R1,R2,E>& G ) : AbstractBellmanFord<T,ll,R1,R2,E>( G , Monoid<>::Object() , 4611686018427387904 ) {}

template <typename T , typename U , typename R1 , typename R2 , typename E> const U& AbstractBellmanFord<T,U,R1,R2,E>::Infty() const { return m_infty; }

template <typename T , typename U , typename R1 , typename R2 , typename E>
tuple<bool,vector<U>> AbstractBellmanFord<T,U,R1,R2,E>::GetDistance( const T& t_start )
{

  BELLMAN_FORD_BODY( , );
  m_p_G->Reset();
  return { valid , move( weight ) };

}

template <typename T , typename U , typename R1 , typename R2 , typename E>
tuple<bool,vector<U>,vector<list<T>>> AbstractBellmanFord<T,U,R1,R2,E>::GetPath( const T& t_start )
{

  BELLMAN_FORD_BODY( vector<int> prev( size ) , prev[j] = i );
  vector<list<T>> path( size );

  if( valid ){
    
    for( int j = 0 ; j < size ; j++ ){

      list<T>& path_j = path[j];
      int i = j;

      while( i != i_start ){

	path_j.push_front( m_p_G->Enumeration( i ) );
	i = prev[i];

      }

      path_j.push_front( t_start );

    }

  }

  m_p_G->Reset();
  return { valid , move( weight ) , move( path ) };

}

// AAA 常設でないライブラリは以上に挿入する。

inline void Solve()
{
  CIN( int , N , M , r );
  gE<path>.resize( N );
  FOR( j , 0 , M ){
    CIN( int , uj , vj );
    CIN( ll , wj );
    gE<path>[uj].push_back( { vj , wj } );
  }
  Graph graph{ N , Get( gE<path> ) };
  BellmanFord bf{ graph };
  auto [b,weight] = bf.GetDistance( r );
  if( b ){
    FOR( i , 0 , N ){
      if( weight[i] == bf.Infty() ){
	COUT( "INF" );
      } else {
	COUT( weight[i] );
      }
    }
  } else {
    COUT( "NEGATIVE CYCLE" );
  }
}
REPEAT_MAIN(1);
accuracy: 1
time_ms: 30
memory_kb: 3544
final_rank: 5

code_snippet: #ifdef DEBUG
  #define _GLIBCXX_DEBUG
  #define REPEAT_MAIN( BOUND ) START_MAIN; signal( SIGABRT , &AlertAbort ); AutoCheck( exec_mode , use_getline ); if( exec_mode == sample_debug_mode || exec_mode == submission_debug_mode || exec_mode == library_search_mode ){ return 0; } else if( exec_mode == experiment_mode ){ Experiment(); return 0; } else if( exec_mode == small_test_mode ){ SmallTest(); return 0; }; DEXPR( int , bound_test_case_num , BOUND , min( BOUND , 100 ) ); int test_case_num = 1; if( exec_mode == solve_mode ){ if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } } else if( exec_mode == random_test_mode ){ CERR( "ランダムテストを行う回数を指定してください。" ); SET_LL( test_case_num ); } FINISH_MAIN
  #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , DEBUG_VALUE )
  #define ASSERT( A , MIN , MAX ) CERR( "ASSERTチェック： " , ( MIN ) , ( ( MIN ) <= A ? "<=" : ">" ) , A , ( A <= ( MAX ) ? "<=" : ">" ) , ( MAX ) ); assert( ( MIN ) <= A && A <= ( MAX ) )
  #define SET_ASSERT( A , MIN , MAX ) if( exec_mode == solve_mode ){ SET_LL( A ); ASSERT( A , MIN , MAX ); } else if( exec_mode == random_test_mode ){ CERR( #A , " = " , ( A = GetRand( MIN , MAX ) ) ); } else { assert( false ); }
  #define SOLVE_ONLY static_assert( __FUNCTION__[0] == 'S' )
  #define CERR( ... ) VariadicCout( cerr , __VA_ARGS__ ) << endl
  #define COUT( ... ) VariadicCout( cout << "出力： " , __VA_ARGS__ ) << endl
  #define CERR_A( A , N ) OUTPUT_ARRAY( cerr , A , N ) << endl
  #define COUT_A( A , N ) cout << "出力： "; OUTPUT_ARRAY( cout , A , N ) << endl
  #define CERR_ITR( A ) OUTPUT_ITR( cerr , A ) << endl
  #define COUT_ITR( A ) cout << "出力： "; OUTPUT_ITR( cout , A ) << endl
#else
  #pragma GCC optimize ( "O3" )
  #pragma GCC optimize ( "unroll-loops" )
  #pragma GCC target ( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" )
  #define REPEAT_MAIN( BOUND ) START_MAIN; CEXPR( int , bound_test_case_num , BOUND ); int test_case_num = 1; if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } FINISH_MAIN
  #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , VALUE )
  #define ASSERT( A , MIN , MAX ) assert( ( MIN ) <= A && A <= ( MAX ) )
  #define SET_ASSERT( A , MIN , MAX ) SET_LL( A ); ASSERT( A , MIN , MAX )
  #define SOLVE_ONLY 
  #define CERR( ... ) 
  #define COUT( ... ) VariadicCout( cout , __VA_ARGS__ ) << ENDL
  #define CERR_A( A , N ) 
  #define COUT_A( A , N ) OUTPUT_ARRAY( cout , A , N ) << ENDL
  #define CERR_ITR( A ) 
  #define COUT_ITR( A ) OUTPUT_ITR( cout , A ) << ENDL
#endif
#ifdef REACTIVE
  #define ENDL endl
#else
  #define ENDL "\n"
#endif
#ifdef USE_GETLINE
  #define SET_LL( A ) { GETLINE( A ## _str ); A = stoll( A ## _str ); }
  #define GETLINE_SEPARATE( SEPARATOR , ... ) SOLVE_ONLY; string __VA_ARGS__; VariadicGetline( cin , SEPARATOR , __VA_ARGS__ )
  #define GETLINE( ... ) SOLVE_ONLY; GETLINE_SEPARATE( '\n' , __VA_ARGS__ )
#else
  #define SET_LL( A ) cin >> A
  #define CIN( LL , ... ) SOLVE_ONLY; LL __VA_ARGS__; VariadicCin( cin , __VA_ARGS__ )
  #define SET_A( A , N ) SOLVE_ONLY; FOR( VARIABLE_FOR_CIN_A , 0 , N ){ cin >> A[VARIABLE_FOR_CIN_A]; }
  #define CIN_A( LL , A , N ) vector<LL> A( N ); SET_A( A , N );
#endif
#include <bits/stdc++.h>
using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using lld = __float128;
template <typename INT> using T2 = pair<INT,INT>;
template <typename INT> using T3 = tuple<INT,INT,INT>;
template <typename INT> using T4 = tuple<INT,INT,INT,INT>;
using path = pair<int,ll>;
#define ATT __attribute__( ( target( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" ) ) )
#define START_MAIN int main(){ ios_base::sync_with_stdio( false ); cin.tie( nullptr )
#define FINISH_MAIN REPEAT( test_case_num ){ if constexpr( bound_test_case_num > 1 ){ CERR( "testcase " , VARIABLE_FOR_REPEAT_test_case_num , ":" ); } Solve(); CERR( "" ); } }
#define START_WATCH chrono::system_clock::time_point watch = chrono::system_clock::now()
#define CURRENT_TIME static_cast<double>( chrono::duration_cast<chrono::microseconds>( chrono::system_clock::now() - watch ).count() / 1000.0 )
#define CHECK_WATCH( TL_MS ) ( CURRENT_TIME < TL_MS - 100.0 )
#define TYPE_OF( VAR ) decay_t<decltype( VAR )>
#define CEXPR( LL , BOUND , VALUE ) constexpr LL BOUND = VALUE
#define CIN_ASSERT( A , MIN , MAX ) TYPE_OF( MAX ) A; SET_ASSERT( A , MIN , MAX )
#define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( TYPE_OF( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ )
#define FOREQ( VAR , INITIAL , FINAL ) for( TYPE_OF( FINAL ) VAR = INITIAL ; VAR <= FINAL ; VAR ++ )
#define FOREQINV( VAR , INITIAL , FINAL ) for( TYPE_OF( INITIAL ) VAR = INITIAL ; VAR + 1 > FINAL ; VAR -- )
#define AUTO_ITR( ARRAY ) auto itr_ ## ARRAY = ARRAY .begin() , end_ ## ARRAY = ARRAY .end()
#define FOR_ITR( ARRAY ) for( AUTO_ITR( ARRAY ) , itr = itr_ ## ARRAY ; itr_ ## ARRAY != end_ ## ARRAY ; itr_ ## ARRAY ++ , itr++ )
#define REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT_ ## HOW_MANY_TIMES , 0 , HOW_MANY_TIMES )
#define SET_PRECISION( DECIMAL_DIGITS ) cout << fixed << setprecision( DECIMAL_DIGITS )
#define OUTPUT_ARRAY( OS , A , N ) FOR( VARIABLE_FOR_OUTPUT_ARRAY , 0 , N ){ OS << A[VARIABLE_FOR_OUTPUT_ARRAY] << (VARIABLE_FOR_OUTPUT_ARRAY==N-1?"":" "); } OS
#define OUTPUT_ITR( OS , A ) { auto ITERATOR_FOR_OUTPUT_ITR = A.begin() , END_FOR_OUTPUT_ITR = A.end(); bool VARIABLE_FOR_OUTPUT_ITR = ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR; while( VARIABLE_FOR_OUTPUT_ITR ){ OS << *ITERATOR_FOR_COUT_ITR; ( VARIABLE_FOR_OUTPUT_ITR = ++ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR ) ? OS : OS << " "; } } OS
#define RETURN( ... ) SOLVE_ONLY; COUT( __VA_ARGS__ ); return
#define COMPARE( ... ) auto naive = Naive( __VA_ARGS__ ); auto answer = Answer( __VA_ARGS__ ); bool match = naive == answer; COUT( "(" , #__VA_ARGS__ , ") == (" , __VA_ARGS__ , ") : Naive == " , naive , match ? "==" : "!=" , answer , "== Answer" ); if( !match ){ return; }

// 入出力用
template <class Traits> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is ) { return is; }
template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is , Arg& arg , ARGS&... args ) { return VariadicCin( is >> arg , args... ); }
template <class Traits> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator ) { return is; }
template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator , Arg& arg , ARGS&... args ) { return VariadicGetline( getline( is , arg , separator ) , separator , args... ); }
template <class Traits , typename Arg> inline basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os , const vector<Arg>& arg ) { auto begin = arg.begin() , end = arg.end(); auto itr = begin; while( itr != end ){ ( itr == begin ? os : os << " " ) << *itr; itr++; } return os; }
template <class Traits , typename Arg> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg& arg ) { return os << arg; }
template <class Traits , typename Arg1 , typename Arg2 , typename... ARGS> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg1& arg1 , const Arg2& arg2 , const ARGS&... args ) { return VariadicCout( os << arg1 << " " , arg2 , args... ); }

// デバッグ用
#ifdef DEBUG
  inline void AlertAbort( int n ) { CERR( "abort関数が呼ばれました。assertマクロのメッセージが出力されていない場合はオーバーフローの有無を確認をしてください。" ); }
  void AutoCheck( int& exec_mode , const bool& use_getline );
  inline void Solve();
  inline void Experiment();
  inline void SmallTest();
  inline void RandomTest();
  ll GetRand( const ll& Rand_min , const ll& Rand_max );
  int exec_mode;
  CEXPR( int , solve_mode , 0 );
  CEXPR( int , sample_debug_mode , 1 );
  CEXPR( int , submission_debug_mode , 2 );
  CEXPR( int , library_search_mode , 3 );
  CEXPR( int , experiment_mode , 4 );
  CEXPR( int , small_test_mode , 5 );
  CEXPR( int , random_test_mode , 6 );
  #ifdef USE_GETLINE
    CEXPR( bool , use_getline , true );
  #else
    CEXPR( bool , use_getline , false );
  #endif
#else
  ll GetRand( const ll& Rand_min , const ll& Rand_max ) { ll answer = time( NULL ); return answer * rand() % ( Rand_max + 1 - Rand_min ) + Rand_min; }
#endif

// 圧縮用
#define TE template
#define TY typename
#define US using
#define ST static
#define IN inline
#define CL class
#define PU public
#define OP operator
#define CE constexpr
#define CO const
#define NE noexcept
#define RE return 
#define WH while
#define VO void
#define VE vector
#define LI list
#define BE begin
#define EN end
#define SZ size
#define MO move
#define TH this
#define CRI CO int&
#define CRUI CO uint&
#define CRL CO ll&

// VVV 常設ライブラリは以下に挿入する。
// Map
// c:/Users/user/Documents/Programming/Mathematics/Function/Map
CL is_ordered{PU:is_ordered()= delete;TE <TY T> ST CE auto Check(CO T& t)-> decltype(t < t,true_type());ST CE false_type Check(...);TE <TY T> ST CE CO bool value = is_same_v< decltype(Check(declval<T>())),true_type >;};
TE <TY T , TY U>US Map = conditional_t<is_constructible_v<unordered_map<T,int>>,unordered_map<T,U>,conditional_t<is_ordered::value<T>,map<T,U>,void>>;
// AAA 常設ライブラリは以上に挿入する。

// グラフ用
template <typename PATH> vector<list<PATH> > gE;
template <typename T , template <typename...> typename V> inline auto Get( const V<T>& a ) { return [&]( const int& i ){ return a[i]; }; }


// 圧縮時は中身だけ削除する。
inline void Experiment()
{
}

// 圧縮時は中身だけ削除する。
inline void SmallTest()
{
}

// VVV 常設でないライブラリは以下に挿入する。

#define BELLMAN_FORD_BODY( INITIALISE_PREV , SET_PREV )			\
  static const U& unit = Unit();					\
  assert( unit < m_infty );				\
  const int i_start = e_inv( t_start );					\
  vector<bool> found( m_size );						\
  weight = vector<U>( m_size , m_infty );				\
  found[i_start] = true;						\
  weight[i_start] = 0;							\
  INITIALISE_PREV;							\
									\
  for( int length = 0 ; length < m_size ; length++ ){			\
  									\
    for( int i = 0 ; i < m_size ; i++ ){				\
									\
      if( found[i] ){							\
									\
	const U& weight_i = weight[i];					\
	assert( weight_i != m_infty );					\
	list<pair<int,U>> edge_i = m_edge( e( i ) );			\
									\
	for( auto itr_edge_i = edge_i.begin() , end_edge_i = edge_i.end() ; itr_edge_i != end_edge_i ; itr_edge_i++ ){ \
									\
	  const int& j = e_inv( itr_edge_i->first );			\
	  const U& edge_ij = itr_edge_i->second;			\
	  U& weight_j = weight[j];					\
	  U temp = Addition( weight_i , edge_ij );			\
									\
	  if( weight_j > temp ){					\
									\
	    found[j] = true;						\
	    weight_j = move( temp );					\
	    SET_PREV;							\
									\
	  }								\
									\
	}								\
									\
      }									\
									\
    }									\
									\
  }									\
									\
  bool valid = true;							\
									\
  for( int i = 0 ; i < m_size && valid ; i++ ){				\
									\
    if( found[i] ){							\
									\
      const U& weight_i = weight[i];					\
      list<pair<int,U>> edge_i = m_edge( e( i ) );			\
									\
      for( auto itr_edge_i = edge_i.begin() , end_edge_i = edge_i.end() ; itr_edge_i != end_edge_i ; itr_edge_i++ ){ \
									\
	const int& j = e_inv( itr_edge_i->first );			\
	const U& edge_ij = itr_edge_i->second;				\
	U& weight_j = weight[j];					\
	const U temp = Addition( weight_i , edge_ij );			\
									\
	if( weight_j > temp ){						\
									\
	  valid = false;						\
	  break;							\
									\
	}								\
									\
      }									\
									\
    }									\
									\
  }									\

// Eは写像edge:T->(T \times U)^{< \omega}に相当する型。
// メモリが不足する場合はEの定義を前計算しないでその都度計算させること。
template <typename T , typename U , typename E>
class BellmanFord_Body
{

protected:
  int m_size;

private:
  U m_infty;
  E m_edge;

public:
  inline BellmanFord_Body( const int& size , const U& infty , E edge );
  // 負の閉路が存在すればfalse、存在しなければtrue
  bool Solve( const T& t_start , vector<U>& weight );
  bool Solve( const T& t_start , vector<U>& weight , vector<list<T>>& path );
  
  const U& Infty() const;
  
private:
  virtual const U& Unit() const = 0;
  virtual U Addition( const U& , const U& ) const = 0;
  virtual T e( const int& i ) = 0;
  virtual int e_inv( const T& t ) = 0;
  virtual void Reset();

};

// 入力の範囲内で要件
// (1) edgeの値の各成分の第2成分が0以上である。
// (2) 2^{31}-1がEの値の各成分の第2成分size個以下の和で表せるいかなる数よりも大きい。
// (6) Vの各要素u,vに対し、辺u->vが複数存在する場合は重みが最小のものが前にpushされている。
// が成り立つ場合にのみサポート。

// 単一始点全終点最短経路探索／経路復元なしO(size |edge|)
// 単一始点全終点最短経路探索／経路復元ありO(size |edge|)
template <typename E>
class BellmanFord :
  public BellmanFord_Body<int,ll,E>
{

public:
  inline BellmanFord( const int& size , E edge );
  
private:
  inline const ll& Unit() const;
  inline ll Addition( const ll& , const ll& ) const;
  inline int e( const int& i );
  inline int e_inv( const int& t );

};

template <typename T , typename U , typename M_U , typename E_U , typename E>
class MonoidForBellmanFord :
  public BellmanFord_Body<T,U,E>
{

private:
  M_U m_m_U;
  E_U m_e_U;

public:
  inline MonoidForBellmanFord( const int& size , M_U m_U , E_U e_U , const U& infty , E edge );

private:
  inline const U& Unit() const;
  inline U Addition( const U& , const U& ) const;

};

// 入力の範囲内で要件
// (1) edgeの値の各成分の第2成分がe_U()以上である。
// (2) inftyがEの値の各成分の第2成分size個以下の和で表せるいかなる項よりも大きい。
// (3) foundがEの値の各成分の第2成分size個以下の和で表せず、inftyとも異なる。
// (4) (U,m_U:U^2->U,e_U:1->U)がbool operator<(const U&,const U&)に関して全順序モノイドである。
// (6) Vの各要素u,vに対し、辺u->vが複数存在する場合は重みが最小のものが前にpushされている。
// (7) edgeはデフォルト引数による呼び出し可能（推論補助に用いる）
// が成り立つ場合にのみサポート。

// 単一始点全終点最短経路探索／経路復元なしO(size |edge| log size)
// 単一始点全終点最短経路探索／経路復元ありO(size |edge| log size)
template <typename T , typename U , typename M_U , typename E_U , typename E>
class MemorisationBellmanFord :
  public MonoidForBellmanFord<T,U,M_U,E_U,E>
{

private:
  int m_length;
  Map<T,int> m_memory;
  vector<T> m_memory_inv;

public:
  inline MemorisationBellmanFord( const int& size , M_U m_U , E_U e_U , const U& infty , E edge );
  
private:
  inline T e( const int& i );
  inline int e_inv( const T& t );
  inline void Reset();

};
template<typename U , typename M_U , typename E_U , typename E> MemorisationBellmanFord( const int& , M_U , E_U , const U& , E ) -> MemorisationBellmanFord<decltype(declval<E>()(0).front().first),U,M_U,E_U,E>;

// 入力の範囲内で要件
// (1) edgeの値の各成分の第2成分がe_U()以上である。
// (2) inftyがEの値の各成分の第2成分size個以下の和で表せるいかなる項よりも大きい。
// (3) foundがEの値の各成分の第2成分size個以下の和で表せず、inftyとも異なる。
// (4) (U,m_U:U^2->U,e_U:1->U)がbool operator<(const U&,const U&)に関して全順序モノイドである。
// (5) (enum_T,enum_T_inv)が互いに逆写像である。
// (6) Vの各要素u,vに対し、辺u->vが複数存在する場合は重みが最小のものが前にpushされている。
// が成り立つ場合にのみサポート。

// 単一始点全終点最短経路探索／経路復元なしO(size |edge|)
// 単一始点全終点最短経路探索／経路復元ありO(size |edge|)
template <typename T , typename Enum_T , typename Enum_T_inv , typename U , typename M_U , typename E_U , typename E>
class EnumerationBellmanFord :
  public MonoidForBellmanFord<T,U,M_U,E_U,E>
{

private:
  Enum_T m_enum_T;
  Enum_T_inv m_enum_T_inv;
  
public:
  inline EnumerationBellmanFord( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , M_U m_U , E_U e_U , const U& infty , E edge );
  
private:
  inline T e( const int& i );
  inline int e_inv( const T& t );

};
template<typename Enum_T , typename Enum_T_inv , typename U , typename M_U , typename E_U , typename E> EnumerationBellmanFord( const int& , Enum_T , Enum_T_inv , M_U , E_U , const U& , E ) -> EnumerationBellmanFord<decltype(declval<Enum_T>()(0)),Enum_T,Enum_T_inv,U,M_U,E_U,E>;

template <typename T , typename U , typename E> inline BellmanFord_Body<T,U,E>::BellmanFord_Body( const int& size , const U& infty , E edge ) : m_size( size ) , m_infty( infty ) , m_edge( move( edge ) ) { static_assert( ! is_same_v<U,int> && is_invocable_r_v<list<pair<T,U>>,E,T> ); }
template <typename E> inline BellmanFord<E>::BellmanFord( const int& size , E edge ) : BellmanFord_Body<int,ll,E>( size , 9223372036854775807 , move( edge ) ) {}
template <typename T , typename U , typename M_U , typename E_U , typename E> inline MonoidForBellmanFord<T,U,M_U,E_U,E>::MonoidForBellmanFord( const int& size , M_U m_U , E_U e_U , const U& infty , E edge ) : BellmanFord_Body<T,U,E>( size , infty , move( edge ) ) , m_m_U( move( m_U ) ) , m_e_U( move( e_U ) ) {}
template <typename T , typename U , typename M_U , typename E_U , typename E> inline MemorisationBellmanFord<T,U,M_U,E_U,E>::MemorisationBellmanFord( const int& size , M_U m_U , E_U e_U , const U& infty , E edge ) : MonoidForBellmanFord<T,U,M_U,E_U,E>( size , move( m_U ) , move( e_U ) , infty , move( edge ) ) , m_length() , m_memory() , m_memory_inv() {}
template <typename T , typename Enum_T , typename Enum_T_inv , typename U , typename M_U , typename E_U , typename E> inline EnumerationBellmanFord<T,Enum_T,Enum_T_inv,U,M_U,E_U,E>::EnumerationBellmanFord( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , M_U m_U , E_U e_U , const U& infty , E edge ) : MonoidForBellmanFord<T,U,M_U,E_U,E>( size , move( m_U ) , move( e_U ) , infty , move( edge ) ) , m_enum_T( move( enum_T ) ) , m_enum_T_inv( move( enum_T_inv ) ) {}

template <typename T , typename U , typename E>
bool BellmanFord_Body<T,U,E>::Solve( const T& t_start , vector<U>& weight )
{

  BELLMAN_FORD_BODY( , );
  Reset();
  return valid;

}

template <typename T , typename U , typename E>
bool BellmanFord_Body<T,U,E>::Solve( const T& t_start , vector<U>& weight , vector<list<T>>& path )
{

  BELLMAN_FORD_BODY( vector<int> prev( m_size ) , prev[j] = i );

  if( valid ){
    
    for( int j = 0 ; j < m_size ; j++ ){

      list<T>& path_j = path[j];
      int i = j;

      while( i != i_start ){

	path_j.push_front( e( i ) );
	i = prev[i];

      }

      path_j.push_front( t_start );

    }

  }

  Reset();
  return valid;

}

template <typename T , typename U , typename E> const U& BellmanFord_Body<T,U,E>::Infty() const { return m_infty; }

template <typename E> inline const ll& BellmanFord<E>::Unit() const { static const ll unit = 0; return unit; }
template <typename T , typename U , typename M_U , typename E_U , typename E> inline const U& MonoidForBellmanFord<T,U,M_U,E_U,E>::Unit() const { return m_e_U(); }

template <typename E> inline ll BellmanFord<E>::Addition( const ll& u0 , const ll& u1 ) const { return u0 + u1; }
template <typename T , typename U , typename M_U , typename E_U , typename E> inline U MonoidForBellmanFord<T,U,M_U,E_U,E>::Addition( const U& u0 , const U& u1 ) const { return m_m_U( u0 , u1 ); }

template <typename E> inline int BellmanFord<E>::e( const int& i ) { return i; }
template <typename T , typename U , typename M_U , typename E_U , typename E> inline T MemorisationBellmanFord<T,U,M_U,E_U,E>::e( const int& i ) { assert( i < m_length ); return m_memory_inv[i]; }
template <typename T , typename Enum_T , typename Enum_T_inv , typename U , typename M_U , typename E_U , typename E> inline T EnumerationBellmanFord<T,Enum_T,Enum_T_inv,U,M_U,E_U,E>::e( const int& i ) { return m_enum_T( i ); }

template <typename E> inline int BellmanFord<E>::e_inv( const int& t ) { return t; }

template <typename T , typename U , typename M_U , typename E_U , typename E> inline int MemorisationBellmanFord<T,U,M_U,E_U,E>::e_inv( const T& t )
{

  using base = BellmanFord_Body<T,U,E>;
  
  if( m_memory.count( t ) == 0 ){

    assert( m_length < base::m_size );
    m_memory_inv.push_back( t );
    return m_memory[t] = m_length++;

  }
  
  return m_memory[t];

}

template <typename T , typename Enum_T , typename Enum_T_inv , typename U , typename M_U , typename E_U , typename E> inline int EnumerationBellmanFord<T,Enum_T,Enum_T_inv,U,M_U,E_U,E>::e_inv( const T& t ) { return m_enum_T_inv( t ); }

template <typename T , typename U , typename E> inline void BellmanFord_Body<T,U,E>::Reset() {}
template <typename T , typename U , typename M_U , typename E_U , typename E> inline void MemorisationBellmanFord<T,U,M_U,E_U,E>::Reset() { m_length = 0; m_memory.clear(); m_memory_inv.clear(); }

// AAA 常設でないライブラリは以上に挿入する。

inline void Solve()
{
  CIN( int , N , M , r );
  gE<path>.resize( N );
  FOR( j , 0 , M ){
    CIN( int , uj , vj );
    CIN( ll , wj );
    gE<path>[uj].push_back( { vj , wj } );
  }
  BellmanFord bf{ N , Get( gE<path> ) };
  vector<ll> weight;
  if( bf.Solve( r , weight ) ){
    FOR( i , 0 , N ){
      if( weight[i] == bf.Infty() ){
	COUT( "INF" );
      } else {
	COUT( weight[i] );
      }
    }
  } else {
    COUT( "NEGATIVE CYCLE" );
  }
}
REPEAT_MAIN(1);
accuracy: 1
time_ms: 30
memory_kb: 3472
final_rank: 3