#define _CRT_SECURE_NO_WARNINGS
// #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;
#define all(c) begin(c), end(c)
#define range(i,a,b) for(int i = a; i < (int)(b); i++)
#define rep(i,b) range(i,0,b)
#define eb emplace_back
typedef long long ll;
#define int ll
auto const inf = numeric_limits<int>::max()/4;
 
using Weight = int;
using Capacity = int;
struct Edge {
    int src, dst; Weight weight;
    Edge(int s, int d, int w) : src(s), dst(d), weight(w) {}
};
using Edges = vector<Edge>;
using Graph = vector<Edges>;
using Array = vector<Weight>;
using Matrix = vector<Array>;
 
pair<vector<Weight>, bool> spfa(const Graph &g, int s){
    const Weight inf = numeric_limits<Weight>::max()/4;
    const int n = g.size(); priority_queue<int> q;
    vector<Weight> dist(n, inf); vector<int> inQ(n);
    vector<int> count(n);
    dist[s] = 0; q.emplace(s); inQ[s] = true; ++count[s];
    bool negCycle = false;
    for(int i = 0; q.size(); i++){
        int v = q.top(); q.pop(); inQ[v] = false;
        for(auto &e : g[v]){
            if(dist[v] != inf && dist[e.dst] > dist[v] + e.weight){
                dist[e.dst] = dist[v] + e.weight;
                if(!inQ[e.dst]){
                    q.emplace(e.dst); inQ[e.dst] = true; ++count[e.dst];
                    if(count[e.dst] >= n){ negCycle = true; goto END; }
                }
            }
        }
    }
 END:;
    return make_pair(dist, !negCycle);
}
 
signed main(){
    int V,E,r;
    while(cin >> V >> E >> r){
        Graph g(V);
        rep(i,E){
            int a,b,c;
            cin >> a >> b >> c;
            g[a].eb(a,b,c);
        }
        bool ok;
        vector<Weight> dist;
        tie(dist, ok) = spfa(g,r);
        if(ok){
            for(int i = 0; i < (int)dist.size(); i++){
                if(dist[i] == inf) cout << "INF";
                else cout << dist[i];
                cout << endl;
            }
        } else {
            cout << "NEGATIVE CYCLE" << endl;
        }
    }
}
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<cmath>
#include<climits>
#include<ctime>
#include<cstring>
#include<stack>
#include<queue>
#include<sstream>
#include<string>


#define ALL(v) (v).begin(),(v).end()
#define REP(i,p,n) for(int i=p;i<(int)(n);++i)
#define rep(i,n) REP(i,0,n)
#define DUMP(list) cout << "{ "; for(auto nth : list){ cout << nth << " "; } cout << "}" << endl
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i);

using namespace std;

const int MAX_V = 100001;
const long long INF = 1e12;

int n,m,r;

struct edge{
	int to, dist;
	edge(int t_to,int t_dist){
		to=t_to;dist=t_dist;
	}
};

typedef pair<int,int> P;//cost??¨v

vector< vector<edge> > G(MAX_V);
long long d[MAX_V];

void dijkstra(int s){
	priority_queue<P,vector<P>,greater<P> > que;
	fill_n((long long *)d, sizeof(d)/sizeof(long long),INF);
	d[s] = 0;
	que.push(P(0,s));

	while(!que.empty()){
		P p = que.top(); que.pop();
		int v = p.second;
		if(d[v]<p.first) continue;
		rep(i,G[v].size()){
			edge e = G[v][i];
			if(d[e.to] > d[v] + e.dist){//??????????????´???
				d[e.to] = d[v] + e.dist;
				que.push(P(d[e.to],e.to));
			}
		}
	}
}


int main(){

	cin >> n >> m >> r;

//	G.clear();
//	G.resize(n);

	rep(i,m){
		int a,b,d;
		cin >> a >> b >> d;
		edge tmp1(b,d);
		G[a].push_back(tmp1);
	}

	dijkstra(r);
	rep(i,n){
		//if(i==r) continue;
		if(d[i]==INF) cout << "INF" <<endl;
		else cout << d[i] << endl;
	}

}