Problem:
Single Source Shortest Path (Negative Edges)

Input

An edge-weighted graph G (V, E) and the source r.

|V| |E| r
s0 t0 d0
s1 t1 d1
:
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.

si and ti represent source and target vertices of i-th edge (directed) and di 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

c0
c1
:
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 ≤ di ≤ 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

Solution in C++14 (judge verdict: Accepted)

#include <vector>
#include <stack>
#include <queue>

#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
using std::cin;


template <typename CostType>
/// \brief 辺の情報
struct Edge{
  int to;
  CostType cost;
  Edge(int t,CostType c):to(t),cost(c){}
};

template <typename CostType>
class Graph{

private:





  /// \brief adjacent_list_[n]=ノードnの隣接リストを表すvector<Edge>
  std::vector<std::vector<Edge<CostType>>> adjacent_list_;

public:

  /// \brief 頂点数
  const int NODE_SIZE_;

  /// \brief コンストラクタ
  /// \param node_size 頂点数
  explicit Graph(const int node_size):NODE_SIZE_(node_size),adjacent_list_(node_size){}

  /// \brief 有向グラフの辺を生やす
  /// \param from 辺の根本の頂点の番号
  /// \param to 辺の先の頂点の番号
  /// \param cost 辺のコスト
  void SetDirectedEdge(const int from,const int to,const CostType cost){
    adjacent_list_[from].push_back(Edge<CostType>(to,cost));
  }

  /// \brief 無向グラフの辺を生やす
  /// \param node_a 一方の頂点の番号
  /// \param node_b もう一方の頂点の番号
  /// \param cost 辺のコスト
  void SetUndirectedEdge(const int node_a,const int node_b,const CostType cost){
    SetDirectedEdge(node_a,node_b,cost);
    SetDirectedEdge(node_b,node_a,cost);
  }

  /// \brief ある頂点の隣接リストを取得
  /// \param node_num 頂点の番号
  /// \return 隣接リスト
  std::vector<Edge<CostType>> GetAdjacentList(int node_num)const{
    return adjacent_list_[node_num];
  }
};

/// \brief ダイクストラ法により，ある頂点からの最短経路を求める
/// \tparam CostType 辺のコストの型
/// \param graph グラフ
/// \param start_node どの頂点から最短経路を求めるか
/// \param INF CostType型で十分大きい値
/// \return グラフの各頂点への最短経路を示す配列(到達不可能なときはINF)，負の辺が入っていた場合はsize0の配列
template <typename CostType>
std::vector<CostType> Dijkstra(const Graph<CostType>& graph, const int start_node, CostType INF){
  struct Info{
    int node;
    CostType cost;
    Info(int n,CostType c):node(n),cost(c){};
    bool operator>(const Info& another)const{
      return cost>another.cost;
    }
  };

  std::vector<CostType> min_cost(graph.NODE_SIZE_);
  std::priority_queue<Info,std::vector<Info>,std::greater<Info>> pq;
  for(int i=0;i<min_cost.size();i++){
    min_cost[i]=(i==start_node)?0:INF;
  }
  pq.push(Info(start_node,0));

  while(!pq.empty()){
    Info current_info=pq.top();
    pq.pop();
    if(min_cost[current_info.node]!=current_info.cost) continue;
    const std::vector<Edge<CostType>>& adjacency_list=graph.GetAdjacentList(current_info.node);
    for(auto e:adjacency_list){
      if(min_cost[e.to]>min_cost[current_info.node]+e.cost){
        min_cost[e.to]=min_cost[current_info.node]+e.cost;
        pq.push(Info(e.to,min_cost[e.to]));
      }
    }
  }

  return min_cost;

}

/// \brief ベルマンフォード法により，ある頂点からの最短経路を求める
/// \tparam CostType 辺のコストの型
/// \param graph グラフ
/// \param start_node どの頂点から最短経路を求めるか
/// \param INF CostType型で十分大きい値
/// \return グラフの各頂点への最短経路を示す配列(到達不可能なときはINF)，負の閉路が入っていた場合はsize0の配列
template <typename CostType>
std::vector<CostType> BellmanFord(const Graph<CostType>& graph, const int start_node, CostType INF){
  std::vector<CostType> min_cost(graph.NODE_SIZE_);
  for(int i=0;i<min_cost.size();i++){
    min_cost[i]=(i==start_node)?0:INF;
  }

  for(int loop=0;loop<graph.NODE_SIZE_;loop++){
    for(int from=0;from<graph.NODE_SIZE_;from++){
      if(min_cost[from]==INF) continue;
      std::vector<Edge<CostType>> adjacent_list=graph.GetAdjacentList(from);
      for(auto e:adjacent_list){
        CostType next_cost=min_cost[from]+e.cost;
        if(next_cost<min_cost[e.to]){
          if(loop==graph.NODE_SIZE_-1){
            return std::vector<CostType>(0);
          }else{
            min_cost[e.to]=next_cost;
          }
        }
      }
    }
  }

  return min_cost;
}



/// \brief BFS，DFSをするときに必要な情報をまとめた構造体
struct State{
  int current_node;
  int prev_node;
  //その他必要な情報を入れる
};

/// \brief BFS，DFSの停止条件を入れる
/// \param state 判定対象の状態
/// \return 停止するべきであればtrue
bool ShouldStop(const State& state){

}

/// \brief 幅優先探索(BFS)をする
/// \tparam CostType グラフの辺のコストの型
/// \param graph グラフ
/// \param start_state 初期状態
/// \attention 単なるフレームワークのため，問題ごとに適当に実装して使う
template <typename CostType>
void BFS(const Graph<CostType>& graph,const State& start_state){
  std::queue<State> queue;
  queue.push(start_state);
  while(!queue.empty()){
    State current_state=queue.front();
    queue.pop();

    //必要があればShouldStop()を実装して下の行をコメントアウト
    //if(ShouldStop(current_state) return;

    //current_stateに対してなにかする

    std::vector<Edge<CostType>> adjacent_list=graph.GetAdjacentList(current_state.current_node);
    for(auto e:adjacent_list){

      int next_node=e.to;

      if(next_node!=current_state.current_node){
        State next_state;
        next_state.prev_node=current_state.current_node;
        next_state.current_node=next_node;
        //その他，next_stateに必要な処理を加える

        queue.push(next_state);
      }

    }
  }
}

/// \brief 深さ優先探索(DFS)をする
/// \tparam CostType グラフの辺のコストの型
/// \param graph グラフ
/// \param start_state 初期状態
/// \attention 単なるフレームワークのため，問題ごとに適当に実装して使う

template <typename CostType>
void DFS(const Graph<CostType>& graph,const State& start_state){
  std::stack<State> stack;
  stack.push(start_state);
  while(!stack.empty()){
    State current_state=stack.top();
    stack.pop();

    //必要があればShouldStop()を実装して下の行をコメントアウト
    //if(ShouldStop(current_state) return;

    //current_stateに対してなにかする

    std::vector<Edge<CostType>> adjacent_list=graph.GetAdjacentList(current_state.current_node);
    for(auto e:adjacent_list){

      int next_node=e.to;

      if(next_node!=current_state.current_node){
        State next_state;
        next_state.prev_node=current_state.current_node;
        next_state.current_node=next_node;
        //その他，next_stateに必要な処理を加える

        stack.push(next_state);
      }

    }
  }
}



int main(void){

  int64_t v,e,r;
  cin>>v>>e>>r;
  Graph<int64_t> graph(v);
  for(int64_t i=0;i<e;i++){
    int64_t s,t,d;
    cin>>s>>t>>d;
    graph.SetDirectedEdge(s,t,d);
  }
  const int64_t INF=INT64_MAX/3;
  std::vector<int64_t> result=BellmanFord(graph,r,INF);
  if(result.empty()){
    cout<<"NEGATIVE CYCLE"<<endl;
    return 0;
  }
  for(auto re:result){
    if(re==INF){
      cout<<"INF"<<endl;
    }else{
      cout<<re<<endl;
    }
  }



  return 0;
}