Problem:
All Pairs Shortest Path
Input
An edge-weighted graph
G
(
V
,
E
).
|
V
| |
E
|
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.
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), print
NEGATIVE CYCLE
in a line.
Otherwise, print
D
0,0
D
0,1
...
D
0,|V|-1
D
1,0
D
1,1
...
D
1,|V|-1
:
D
|V|-1,0
D
1,1
...
D
|V|-1,|V|-1
The output consists of
|V|
lines. For each
i
th line, print the cost of the shortest path from vertex
i
to each vertex
j
(
j = 0, 1, ... |V|-1
) respectively. If there is no path from vertex
i
to vertex
j
, print "
INF
". Print a space between the costs.
Constraints
1 ≤
|V|
≤ 100
0 ≤
|E|
≤ 9900
-2 × 10
7
≤
d
i
≤ 2 × 10
7
There are no parallel edges
There are no self-loops
Sample Input 1
4 6
0 1 1
0 2 5
1 2 2
1 3 4
2 3 1
3 2 7
Sample Output 1
0 1 3 4
INF 0 2 3
INF INF 0 1
INF INF 7 0
Sample Input 2
4 6
0 1 1
0 2 -5
1 2 2
1 3 4
2 3 1
3 2 7
Sample Output 2
0 1 -5 -4
INF 0 2 3
INF INF 0 1
INF INF 7 0
Sample Input 3
4 6
0 1 1
0 2 5
1 2 2
1 3 4
2 3 1
3 2 -7
Sample Output 3
NEGATIVE CYCLE

Submitted solutions:

code_snippet: // https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/1/GRL_1_C
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
#include <queue>
using namespace std;

struct Edge
{
    int s = 0, t = 0;
    int d = 0;
    bool enabled = false;
    Edge() = default; // デフォルトコンストラクタを追加
    Edge(int s, int t, int d) : s(s), t(t), d(d), enabled(true) {}
};

struct Route
{
    int destination;
    int min_cost;
    size_t num_node;
    Route(int destination, int min_cost, size_t num_node) : destination(destination), min_cost(min_cost), num_node(num_node) {}
};

struct ShortestPath
{
    int destination;
    int cost;
    bool enabled = false;
};

// prim法を踏襲
void get_distances_as_minimum_spannging_tree(int strat_id, const vector<vector<Edge>> &A, vector<ShortestPath> &d, bool &has_negative_cycle)
{
    // 選択済みと隣接する経路(重みと頂点番号)のリスト
    struct Comp
    {
        bool operator()(const Route &a, const Route &b)
        {
            return a.min_cost > b.min_cost;
        }
    };
    priority_queue<Route, deque<Route>, Comp> routes; // 経路キュー

    routes.push(Route(strat_id, 0, 1)); // 出発点への最短コストは0としておく

    while (routes.empty() == false)
    {
        // 最も安い経路を得る
        auto route = routes.top();
        routes.pop();

        if (d[route.destination].enabled && d[route.destination].cost < route.min_cost)
            continue; // 既に経路が見つかっており、そのコストが新しい経路コストよりも小さいなら無視

        if (route.num_node > A.size()) // 経路に含まれる頂点数が総点数を超えている場合
        {
            has_negative_cycle = true; // NEGATIVE CYCLE
            return;
        }

        d[route.destination].cost = route.min_cost;
        d[route.destination].enabled = true;

        // その経路の行き先頂点から隣接する未選択頂点への経路をキューに追加する
        for (Edge edge : A[route.destination])
        {
            if (!edge.enabled)
                continue; // この辺が無効ならスキップ

            int cost = d[route.destination].cost + edge.d; // この経路＋辺のコスト

            if (d[edge.t].enabled) // この辺の行き先の最短経路が見つかっている場合
            {
                if (d[edge.t].cost <= cost)
                {
                    continue; // 既知の最短経路コストの方が新しい経路コスト以下ならスキップ
                }
            }

            // 経路をキューに追加
            routes.push(Route(edge.t, cost, route.num_node + 1));
        }
    }
}

int main()
{
    int num_vertices; // 頂点数
    int num_edges;    // 辺数
    cin >> num_vertices >> num_edges;
    vector<vector<Edge>> A(num_vertices, vector<Edge>(num_vertices)); // 隣接関係

    for (int i = 0; i < num_edges; ++i)
    {
        int s, t, d;
        cin >> s >> t >> d;
        A[s][t] = Edge(s, t, d);
    }

    vector<vector<ShortestPath>> D; // 最短距離行列
    for (int i = 0; i < num_vertices; ++i)
    {
        bool has_negative_cycle = false;      // NegativeCycleかどうか
        vector<ShortestPath> d(num_vertices); // ノードiからの最短距離

        get_distances_as_minimum_spannging_tree(i, A, d, has_negative_cycle);

        if (has_negative_cycle)
        {
            cout << "NEGATIVE CYCLE" << endl;
            return 0;
        }

        D.push_back(d);
    }

    // 結果を出力
    for (int i = 0; i < num_vertices; ++i)
    {
        for (int j = 0; j < num_vertices; ++j)
        {
            if (D[i][j].enabled)
                cout << D[i][j].cost;
            else
                cout << "INF";

            if (j != num_vertices - 1) // 最後の列以外ではスペースを出力
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3736
final_rank: 1

code_snippet: // https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/1/GRL_1_C
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
#include <queue>
using namespace std;

struct Edge
{
    int s = 0, t = 0;
    int d = 0;
    bool enabled = false;
    Edge() = default; // デフォルトコンストラクタを追加
    Edge(int s, int t, int d) : s(s), t(t), d(d), enabled(true) {}
};

struct Route
{
    int destination;
    int min_cost;
    Route(int destination, int min_cost) : destination(destination), min_cost(min_cost) {}
};

struct ShortestPath
{
    int destination;
    int cost;
    bool enabled = false;
};

// prim法を踏襲
void get_distances_as_minimum_spannging_tree(int strat_id, const vector<vector<Edge>> &A, vector<ShortestPath> &d, bool &has_negative_cycle)
{
    // 選択済みと隣接する経路(重みと頂点番号)のリスト
    struct Comp
    {
        bool operator()(const Route &a, const Route &b)
        {
            return a.min_cost > b.min_cost;
        }
    };
    priority_queue<Route, deque<Route>, Comp> routes; // 経路キュー

    routes.emplace(strat_id, 0); // 出発点への最短コストは0としておく

    int cnt = 0;

    while (routes.empty() == false)
    {
        // 最も安い経路を得る
        auto route = routes.top();
        routes.pop();

        if (d[route.destination].enabled && d[route.destination].cost < route.min_cost)
            continue; // 既に経路が見つかっており、そのコストが新しい経路コストよりも小さいなら無視

        d[route.destination].cost = route.min_cost;
        d[route.destination].enabled = true;

        // その経路の行き先頂点から隣接する未選択頂点への経路をキューに追加する
        for (Edge edge : A[route.destination])
        {
            if (!edge.enabled)
                continue; // この辺が無効ならスキップ

            if (cnt > 99000)
            {
                // 辺の数は9900を超えない⇒超えたら負のループがある
                has_negative_cycle = true; // NegativeCycle判定
                return;
            }
            cnt++;

            int cost = d[route.destination].cost + edge.d; // この経路＋辺のコスト

            if (d[edge.t].enabled) // この辺の行き先の最短経路が見つかっている場合
            {
                if (d[edge.t].cost <= cost)
                {
                    continue; // 既知の最短経路コストの方が新しい経路コスト以下ならスキップ
                }
            }

            // 経路をキューに追加
            routes.emplace(edge.t, cost);
        }
    }
}

int main()
{
    int num_vertices; // 頂点数
    int num_edges;    // 辺数
    cin >> num_vertices >> num_edges;
    vector<vector<Edge>> A(num_vertices, vector<Edge>(num_vertices)); // 隣接関係

    for (int i = 0; i < num_edges; ++i)
    {
        int s, t, d;
        cin >> s >> t >> d;
        A[s][t] = Edge(s, t, d);
    }

    vector<vector<ShortestPath>> D; // 最短距離行列
    for (int i = 0; i < num_vertices; ++i)
    {
        bool has_negative_cycle = false;      // NegativeCycleかどうか
        vector<ShortestPath> d(num_vertices); // ノードiからの最短距離

        get_distances_as_minimum_spannging_tree(i, A, d, has_negative_cycle);

        if (has_negative_cycle)
        {
            cout << "NEGATIVE CYCLE" << endl;
            return 0;
        }

        D.push_back(d);
    }

    // 結果を出力
    for (int i = 0; i < num_vertices; ++i)
    {
        for (int j = 0; j < num_vertices; ++j)
        {
            if (D[i][j].enabled)
                cout << D[i][j].cost;
            else
                cout << "INF";

            if (j != num_vertices - 1) // 最後の列以外ではスペースを出力
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}
accuracy: 0.94
time_ms: 50
memory_kb: 3772
final_rank: 9

code_snippet: // https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/1/GRL_1_C
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
#include <queue>
using namespace std;

struct Edge
{
    int s = 0, t = 0;
    int d = 0;
    bool enabled = false;
    Edge() = default; // デフォルトコンストラクタを追加
    Edge(int s, int t, int d) : s(s), t(t), d(d), enabled(true) {}
};

struct Route
{
    int destination;
    int min_cost;
    Route(int destination, int min_cost) : destination(destination), min_cost(min_cost) {}
};

struct ShortestPath
{
    int destination;
    int cost;
    bool enabled = false;
};

// prim法を踏襲
void get_distances_as_minimum_spannging_tree(int strat_id, const vector<vector<Edge>> &A, vector<ShortestPath> &d, bool &has_negative_cycle)
{
    // 選択済みと隣接する経路(重みと頂点番号)のリスト
    struct Comp
    {
        bool operator()(const Route &a, const Route &b)
        {
            return a.min_cost > b.min_cost;
        }
    };
    priority_queue<Route, deque<Route>, Comp> routes; // 経路キュー

    routes.emplace(strat_id, 0); // 出発点への最短コストは0としておく

    int cnt = 0;

    while (routes.empty() == false)
    {
        // 最も安い経路を得る
        auto route = routes.top();
        routes.pop();

        if (d[route.destination].enabled && d[route.destination].cost < route.min_cost)
            continue; // 既に経路が見つかっており、そのコストが新しい経路コストよりも小さいなら無視

        d[route.destination].cost = route.min_cost;
        d[route.destination].enabled = true;

        // その経路の行き先頂点から隣接する未選択頂点への経路をキューに追加する
        for (Edge edge : A[route.destination])
        {
            if (!edge.enabled)
                continue; // この辺が無効ならスキップ

            if (cnt > 9900)
            {
                // 辺の数は9900を超えない⇒超えたら負のループがある
                has_negative_cycle = true; // NegativeCycle判定
                return;
            }
            cnt++;

            int cost = d[route.destination].cost + edge.d; // この経路＋辺のコスト

            if (d[edge.t].enabled) // この辺の行き先の最短経路が見つかっている場合
            {
                if (d[edge.t].cost <= cost)
                {
                    continue; // 既知の最短経路コストの方が新しい経路コスト以下ならスキップ
                }
            }

            // 経路をキューに追加
            routes.emplace(edge.t, cost);
        }
    }
}

int main()
{
    int num_vertices; // 頂点数
    int num_edges;    // 辺数
    cin >> num_vertices >> num_edges;
    vector<vector<Edge>> A(num_vertices, vector<Edge>(num_vertices)); // 隣接関係

    for (int i = 0; i < num_edges; ++i)
    {
        int s, t, d;
        cin >> s >> t >> d;
        A[s][t] = Edge(s, t, d);
    }

    vector<vector<ShortestPath>> D; // 最短距離行列
    for (int i = 0; i < num_vertices; ++i)
    {
        bool has_negative_cycle = false;      // NegativeCycleかどうか
        vector<ShortestPath> d(num_vertices); // ノードiからの最短距離

        get_distances_as_minimum_spannging_tree(i, A, d, has_negative_cycle);

        if (has_negative_cycle)
        {
            cout << "NEGATIVE CYCLE" << endl;
            return 0;
        }

        D.push_back(d);
    }

    // 結果を出力
    for (int i = 0; i < num_vertices; ++i)
    {
        for (int j = 0; j < num_vertices; ++j)
        {
            if (D[i][j].enabled)
                cout << D[i][j].cost;
            else
                cout << "INF";

            if (j != num_vertices - 1) // 最後の列以外ではスペースを出力
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}
accuracy: 0.66
time_ms: 20
memory_kb: 3656
final_rank: 10

code_snippet: #include<iostream>
#include<cstdio>
using namespace std;
const int INF=1e12;
int e,v,r;
long long int to[100000],from[100000],w[1000000],d[1000][1000];
bool relax(int e){
	if(d[r][to[e]]>d[r][from[e]]+w[e] && d[r][from[e]]!=INF){
		d[r][to[e]]=d[r][from[e]]+w[e];
		return 1;
	}
	return 0;
}
int main(){
	cin>>v>>e;
	for(int i=0;i<e;i++){
		cin>>to[i]>>from[i]>>w[i];
	}
	for(int i=0;i<v+10;i++){
		fill(d[i],d[i]+v+10,INF);
	}
	for(r=0;r<v;r++){
		d[r][r]=0;
		for(int i=0;i<v;i++){
			for(int j=0;j<e;j++){
				bool o=relax(j);
				if(i==v-1 && o==true){
					cout<<"NEGATIVE CYCLE"<<endl;
					return 0;
				}
			}
		}
	}
	for(int i=0;i<v;i++){
		for(int j=0;j<v;j++){
			if(d[j][i]!=INF){
				cout<<d[j][i];
			}
			else {
				cout<<"INF";
			}
			if(j!=v-1){
				cout<<" ";
			}
		}
		cout<<endl;
	}
}
accuracy: 1
time_ms: 90
memory_kb: 8156
final_rank: 8

code_snippet: //// From algorithms repository `template.cpp`
// Based on Competitive Programming Book by Steve Halim
// Also has some snippets from previous codes I've written

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<long, long> pll;
typedef pair<int, int> pii;
typedef vector<int> vi;
#define FAST_IO()                   \
  ios_base::sync_with_stdio(false); \
  cin.tie(NULL)

// 2**6 =  64                           // 4!  = 24
// 2**8 =  256                          // 5!  = 120
// 2**10 = 1,024 ~= 10^3                // 6!  = 720
// 2**15 = 32,768                       // 7!  = 5,040
// 2**20 = 1,048,576 ~= 10^6            // 8!  = 40,320
// 2**25 = 33,554,432                   // 9!  = 362,880
// 2**30 = 1,073,741,824                // 10! = 3,628,800 ~= 3*10^6
// 2**32 = 4,294,967,296                // 11! = 39,916,800 ~= 4*10^7
//                                      // 12! = 479,001,600
//                                      // 14! = 87,178,291,200
// int up to  2*10^9 (2^31-1)           // 16! = 20,922,789,888,000
// ll up to   9*10^18 (2^63 -1)         // 18! = 6,402,373,705,728,000
// ull up to 18*10^18 (2^64-1)/         // 20! = 2,432,902,008,176,640,000
// ld up to  10*10^307

// 1 sec is ~10^8 operations

// n                Worst AC algorithm
// <=[10..11]       O(n!), O(n^6)
// <=[17..19]       O(2^n * n^2)
// <=[18..22]       O(2^n * n)
// <=[24..26]       O(2^n)
// <=100            O(n^4)
// <=450            O(n^3)
// <=1.5*10^3       O(n^2.5)
// <=2.5*10^3       O(n^2 * log(n))
// <=10^4           O(n^2)
// <=2*10^5         O(n^1.5)
// <=4.5*10^6       O(n * log(n))
// <=10^7           O(n * log(log(n)))
// <=10^8           O(n), O(log(n)), O(1)

#define INF 1e11

// O(VE)
void bellman_ford(int source, int V, const vector<vector<pair<int, ll>>> &neighbors, vector<ll> &distance, vector<int> &predecessor)
{
  // vector<int> distance(V, INF);
  // vector<int> predecessor(V, -1);

  distance[source] = 0;

  for (int i = 0; i < V - 1; i++) // relax all E edges V−1 times
    for (int u = 0; u < V; u++)   // these next two loops = O(E), overall O(VE)
      if (distance[u] != INF)
        for (int j = 0; j < (int)neighbors[u].size(); j++)
        {
          pair<int, ll> v = neighbors[u][j];
          if (distance[u] + v.second < distance[v.first])
          {
            distance[v.first] = distance[u] + v.second; // relax
            predecessor[v.first] = u;                   // save predecessor
          }
        }
}

bool has_negative_cycle(int V, const vector<vector<pair<int, ll>>> &neighbors, const vector<ll> &distance)
{
  // after running the O(VE) Bellman Ford’s algorithm
  bool hasNegativeCycle = false;

  for (int u = 0; u < V; u++) // one more pass to check
    if (distance[u] != INF)
      for (int i = 0; i < (int)neighbors[u].size(); i++)
      {
        pair<int, ll> v = neighbors[u][i];
        if (distance[v.first] > distance[u] + v.second) // if this is still possible
          hasNegativeCycle = true;                      // then negative cycle exists!
      }

  return hasNegativeCycle;
}

int main()
{
  FAST_IO();

#ifdef DEBUG
  freopen("input.txt", "r", stdin);
  freopen("error.txt", "w", stderr);
  freopen("output.txt", "w", stdout);
#endif

  int V, E;
  cin >> V >> E;

  vector<vector<pair<int, ll>>> neighbors(V, vector<pair<int, ll>>());

  for (int i = 0; i < E; i++)
  {
    int u, v;
    ll w;
    cin >> u >> v >> w;

    neighbors[u].push_back(make_pair(v, w));
  }

  vector<vector<ll>> distance(V, vector<ll>());

  for (int i = 0; i < V; i++)
  {
    int source = i;
    vector<ll> current_distance(V, INF);
    vector<int> predecessor(V, -1);

    bellman_ford(source, V, neighbors, current_distance, predecessor);

    if (has_negative_cycle(V, neighbors, current_distance))
    {
      cout << "NEGATIVE CYCLE" << endl;
      return 0;
    }
    else
    {
      distance[source] = current_distance;
    }
  }

  for (int i = 0; i < V; i++)
  {
    for (int j = 0; j < V; j++)
    {
      if (distance[i][j] == INF)
        cout << "INF";
      else
        cout << distance[i][j];

      if (j < V - 1)
        cout << " ";
    }
    cout << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3684
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <list>
#include <queue>
#include <climits>
#include <sstream>
#include <tuple>

using Path = std::tuple<int, int, int>; // 経路。cost, s, t. 頂点indexから頂点secondを経由した頂点thirdまでの距離はfirst
using Edge = std::pair<int, int>; // 辺。ある点から頂点番号firstまでの距離はsecond
using Graph = std::vector<std::list<Edge>>;

bool isLoop(const std::vector<int>& P, int u) {
    for (int v = P[u]; v >= 0; v = P[v]) if (v == u) return true;
    return false;
}
std::vector<int> sssp(const Graph& G, int index) {
    int n = G.size();
    std::vector<int> D(n, INT_MIN); // 始点から各頂点までの距離、負数は距離未確定
    std::vector<int> P(n, -1);      // 各頂点の親 流入元

    // 始点からの距離が近い順に、距離・頂点番号ペアを保持する
    std::priority_queue<Path, std::deque<Path>, std::greater<Path>> paths;
    paths.emplace(0, -1, index); // 始点から始点までの距離は0

    while(paths.empty() == false) {
        // 始点からの最も近い点を得る
        const auto [d, s, t] = paths.top(); paths.pop();
        if (D[t] != INT_MIN && D[t] <= d) continue; // 高いルートは無視

        // もし、tの親を辿って自身が居たら負の閉路
        P[t] = s;
        D[t] = d;
        if (isLoop(P, t)) return std::vector<int>();

        // 新たな頂点に隣接する頂点の経路を追加する
        for (const auto& [v, c] : G[t]) {
            paths.emplace(D[t] + c, t, v);
        }
    }
    return D;
}

int main() {
    int v, e;
    std::cin >> v >> e;
    Graph G(v);
    for (int i = 0; i < e; ++i) {
        int s, t, d;
        std::cin >> s >> t >> d;
        G[s].emplace_back(t, d);
    }
    std::stringstream ans; 
    for (int i = 0; i < v; ++i) {
        const auto& d = sssp(G, i);
        if (d.empty()) {
            std::cout << "NEGATIVE CYCLE" << std::endl;
            return 0;
        }
        for (int j = 0; j < d.size(); ++j) {
            if (j) ans << " ";
            if (d[j] == INT_MIN) ans << "INF";
            else ans << d[j];
        }
        ans << "\n";
    }
    std::cout << ans.str();
}
accuracy: 1
time_ms: 150
memory_kb: 3856
final_rank: 7

code_snippet: #include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <list>
#include <queue>
#include <climits>
#include <sstream>
#include <tuple>

using Path = std::tuple<int, int, int>; // 経路。cost, s, t. 頂点indexから頂点secondを経由した頂点thirdまでの距離はfirst
using Edge = std::pair<int, int>; // 辺。ある点から頂点番号firstまでの距離はsecond
using Graph = std::vector<std::list<Edge>>;

bool isLoop(const std::vector<int>& P, int u) {
    for (int v = P[u]; v >= 0; v = P[v]) {
       if (v == u) {
        return true;
       }
    }
    return false;
}
std::vector<int> sssp(const Graph& G, int index) {
    int n = G.size();
    std::vector<int> D(n, INT_MIN); // 始点から各頂点までの距離、負数は距離未確定
    std::vector<int> P(n, -1);      // 各頂点の親 流入元

    // 始点からの距離が近い順に、距離・頂点番号ペアを保持する
    std::priority_queue<Path, std::deque<Path>, std::greater<Path>> paths;
    paths.emplace(0, -1, index); // 始点から始点までの距離は0

    while(paths.empty() == false) {
        // 始点からの最も近い点を得る
        const auto [d, s, t] = paths.top(); paths.pop();
        if (D[t] != INT_MIN && D[t] <= d) continue; // 高いルートは無視

        // もし、tの親を辿って自身が居たら負の閉路
        P[t] = s;
        D[t] = d;
        if (isLoop(P, t)) return std::vector<int>();

        // 新たな頂点に隣接する頂点の経路を追加する
        for (const auto& [v, c] : G[t]) {
            paths.emplace(D[t] + c, t, v);
        }
    }
    return D;
}

int main() {
    int v, e;
    std::cin >> v >> e;
    Graph G(v);
    for (int i = 0; i < e; ++i) {
        int s, t, d;
        std::cin >> s >> t >> d;
        G[s].emplace_back(t, d);
    }
    std::stringstream ans; 
    for (int i = 0; i < v; ++i) {
        const auto& d = sssp(G, i);
        if (d.empty()) {
            std::cout << "NEGATIVE CYCLE" << std::endl;
            return 0;
        }
        for (int j = 0; j < d.size(); ++j) {
            if (j) ans << " ";
            if (d[j] == INT_MIN) ans << "INF";
            else ans << d[j];
        }
        ans << "\n";
    }
    std::cout << ans.str();
}
accuracy: 1
time_ms: 150
memory_kb: 3752
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using VI = vector<int>;
using P = pair<int, int>;
constexpr int INF = 2001001001;
constexpr ll LINF = 1001001001001001001ll;
#define rep(i, n) for (ll i = 0; i < (int)(n); i++)
#define rep2(i, k, n) for (ll i = k; i < (int)(n); i++)
//ワーシャルフロイドは盤面(n^2)をn回修正することで回り道ﾙｰﾄの長さが１つずつ減り、最終的にその回り道が全部つながって1本の辺になるイメージ
//または頂点s,tのみに着目するとそれ以外の頂点を１つずつ消して回り道ﾙｰﾄの長さを1つずつ減らしていくイメージ
//だから極論一回当たりの盤面の修正はどこから行っても結局min値をとるだけなので上手くいく
int main(){

    // int ans = 0;
    int n, e;
    cin >> n >> e;
    // vector<vector<int>> v(n, vector<int>(m));
    vector<vector<int>> edge(n, vector<int>(n, INF));
    
    rep(i, n) edge[i][i] = 0;
    rep(i, e){
        int s, t, d;
        cin >> s >> t >> d;
        edge[s][t] = d;//有向辺の場合
    }
    rep(cnt, n) rep(i, n) rep(j, n) rep(k, n) {
        if(edge[i][k] == INF || edge[k][j] == INF) continue;
        edge[i][j] = min(edge[i][j], edge[i][k] + edge[k][j]);
    }
    
    rep(i, n){
        if(edge[i][i] < 0) {
            cout << "NEGATIVE CYCLE" << endl;
            return 0;
        }
    }
    rep(i, n) {
        rep(j, n){
            if(edge[i][j] == INF) cout << "INF";
            else cout << edge[i][j];
            if(j != n-1) cout << ' ';
        }
        cout << "\n";
    } 
    
    
    

}
accuracy: 1
time_ms: 110
memory_kb: 3488
final_rank: 4

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

vector<long long> bellman_ford(int v,int r,const vector<vector<pair<int,long long>>>& graph,bool& has_negative_cycle){
    const long long INF=LLONG_MAX;
    vector<long long> dist(v,INF);
    dist[r]=0;

    for(int i=0;i<v-1;i++){
        for(int u=0;u<v;u++){
            for(auto& [to,weight]:graph[u]){
                if(dist[u]!=INF && dist[u]+weight<dist[to]){
                    dist[to]=dist[u]+weight;
                }
            }
        }
    }
    for(int u=0;u<v;u++){
        for(auto& [to,weight]:graph[u]){
            if(dist[u]!=INF && dist[u]+weight<dist[to]){
                has_negative_cycle=true;
                return {};
            }
        }
    }
    return dist;
}

int main(){
    int v,e;
    cin >> v >> e;
    
    vector<vector<pair<int,long long>>> graph(v);
    rep(i,e){
        int s,t,d;
        cin >> s >> t >> d;
        graph[s].push_back({t,d});
    }

    rep(i,v){
        bool has_negative_cycle=false;
        vector<long long> dist = bellman_ford(v,i,graph,has_negative_cycle);
        if(has_negative_cycle){
            cout << "NEGATIVE CYCLE" << endl;
            return 0;
        }
        rep(j,v){
            if(dist[j]==LLONG_MAX){
                cout << "INF";
            }
            else{
                cout << dist[j];
            }
            if(j<v-1){
                cout << " ";
            }
        }
        cout << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 3560
final_rank: 3

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cmath>
#include<iomanip>
#include<map>
#include<stack>
#include<queue>
#include<set>
#include<deque>
#include<list>
#include<bitset>
using namespace std;
using ll = long long;
using ld = long double;
using P = pair<ll,ll>;

const ld EPS = 1e-10;
const ll MOD = 1000000007LL;
const ll INF = 1LL << 60;
const ld PI = acos( -1.0 );

#define SWAP( A, B ) { auto tmp = A; A = B; B = tmp; }

template <typename T>
void print( vector<T> v ){
    if( v.size() == 0 ) return;
    for( int i = 0 ; i < v.size() - 1 ; i++ )
        cout << v[i] << ' ';
    cout << v[v.size()-1] << endl;
}

struct Edge{

    int to;
    ll cost;

    Edge( int _to, ll _cost ){

        to = _to;
        cost = _cost;

    }

};

struct Graph{

    int size;
    vector< vector<Edge> > adj;

    Graph( int _size ){

        size = _size;
        for( int i = 0 ; i < size ; i++ ){
            vector<Edge> tmp;
            adj.push_back( tmp );
        }

    }

    void dijkstra( int origin ){

        vector<ll> dist( size, INF );
        priority_queue<P> pq;

        dist[origin] = 0;
        pq.push( make_pair( 0, origin ) );
        while( !pq.empty() ){
            P next = pq.top(); pq.pop();
            ll cost = -next.first;
            int to = next.second;
            if( dist[to] < cost ) continue;
            for( int i = 0 ; i < adj[to].size() ; i++ ){
                if( dist[adj[to][i].to] > dist[to] + adj[to][i].cost ){
                    dist[adj[to][i].to] = dist[to] + adj[to][i].cost;
                    pq.push( make_pair( -dist[adj[to][i].to], adj[to][i].to ) );
                }
            }
        }
        for( int i = 0 ; i < size ; i++ ){
            if( dist[i] == INF )
                cout << "INF" << endl;
            else
                cout << dist[i] << endl;
        }

    }

    void bellman_ford( int origin ){

        vector<ll> dist;

        for( int i = 0 ; i < size ; i++ )
            dist.push_back( INF );
        dist[origin] = 0LL;
        for( int i = 0 ; i < size ; i++ ){
            for( int j = 0 ; j < size ; j++ ){
                for( int k = 0 ; k < adj[j].size() ; k++ ){
                    if( dist[j] == INF ) continue;
                    if( i == size - 1 && dist[j] + adj[j][k].cost < dist[adj[j][k].to] ){
                        cout << "NEGATIVE CYCLE" << endl;
                        return;
                    }
                    dist[adj[j][k].to] = min( dist[adj[j][k].to], dist[j] + adj[j][k].cost );
                }
            }
        }
        for( int i = 0 ; i < size ; i++ ){
            if( dist[i] == INF )
                cout << "INF" << endl;
            else
                cout << dist[i] << endl;
        }
    }

    void warshall_floyd(){

        vector<vector<vector<ll>>> dist;

        for( int i = 0 ; i <= size ; i++ ){
            vector<vector<ll>> v1;
            for( int j = 0 ; j < size ; j++ ){
                vector<ll> v2;
                for( int k = 0 ; k < size ; k++ )
                    v2.push_back( INF );
                v1.push_back( v2 );
            }
            dist.push_back( v1 );
        }
        for( int i = 0 ; i < size ; i++ )
            dist[0][i][i] = 0LL;
        for( int i = 0 ; i < size ; i++ ){
            for( int j = 0 ; j < adj[i].size() ; j++ )
                dist[0][i][adj[i][j].to] = adj[i][j].cost;
        }
        for( int i = 1 ; i <= size ; i++ ){
            for( int j = 0 ; j < size ; j++ ){
                for( int k = 0 ; k < size ; k++ ){
                    if( dist[i-1][j][i-1] != INF && dist[i-1][i-1][k] != INF )
                        dist[i][j][k] = min( dist[i-1][j][k], dist[i-1][j][i-1] + dist[i-1][i-1][k] );
                    else 
                        dist[i][j][k] = dist[i-1][j][k];
                }
            }
        }
        for( int i = 0 ; i < size ; i++ ){
            if( dist[size][i][i] < 0 ){
                cout << "NEGATIVE CYCLE" << endl;
                return;
            }
        }
        for( int i = 0 ; i < size ; i++ ){
            for( int j = 0 ; j < size - 1; j++ ){
                if( dist[size][i][j] == INF )
                    cout << "INF" << " ";
                else
                    cout << dist[size][i][j] << " ";
            }
            if( dist[size][i][size-1] == INF )
                cout << "INF" << endl;
            else
                cout << dist[size][i][size-1] << endl;
        }

    }
 
};

int main(){

    int V, E, s, t;
    ll d;

    cin >> V >> E;
    Graph g( V );
    for( int i = 0 ; i < E ; i++ ){
        cin >> s >> t >> d;
        Edge e( t, d );
        g.adj[s].push_back( e );
    }
    g.warshall_floyd();

}
accuracy: 1
time_ms: 10
memory_kb: 11632
final_rank: 5