// File: Manca[P]algorithms2/./assignment4.hpp
// Function: assignment4::floyd_warshall(std::unordered_map<int, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int>>>, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int>>>>>>&, int, int&)
bool floyd_warshall(Graph& graph, int n, int& shortest)
    {
        PROFILE("Initialize Floyd-Warshall")
        std::vector<std::vector<std::vector<int>>> A;       // a 3D array
        // setup sizes (we will store only kth and k-1th result)
        A.resize(2);
        for (int i = 0; i < 2; i++)
        {
            A[i].resize(n+1);
            for (int j = 0; j <= n; j++)
                A[i][j].resize(n+1);
        }
        
        for (int i = 1; i <= n; i++)             // i,j are vertices (from 1 to 1000)
            for (int j = 1; j <= n; j++)
            {
                int cost;
                if (i == j)   A[0][i][j] = 0;
                else if (ijConnected(i, j, graph, cost)) A[0][i][j] = cost;
                else if (i != j)  A[0][i][j] = INT32_MAX/2 -1;
            }

        PROFILE_STOP();

        // the algorithm
        PROFILE("Floyd-Warshall algorithm");
        for (int k = 1; k <= n; k++)
        {
            for (int i = 1; i <= n; i++)
            {
                for (int j = 1; j <= n; j++)
                {
                    A[1][i][j] = std::min(A[0][i][j], A[0][i][k] + A[0][k][j]);
                    A[0][i][j] = A[1][i][j];    // store currently computed value at zero position (previous - interchange)
                }

                // check for negative cycles (if current i-th iteration reveals cycle, abort!)
                if (A[1][i][i] < 0)
                {
                    std::cout << "Negative cycle!! Vertex: " << i << ". Total weight: " << A[1][i][i] << std::endl;
                    PROFILE_STOP();
                    return false;
                }
            }
           
        }
        PROFILE_STOP();

        // find the shortest shortest path
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (i == j) continue;
                if (A[1][i][j] < shortest) shortest = A[1][i][j];
            }
        }

        return true;
    }

// Assembly:
subq $0x168, %rsp            # imm = 0x168
movq %rdi, 0x158(%rsp)
movl %esi, 0x154(%rsp)
movq %rdx, 0x148(%rsp)
callq 0x10a60
movq %rax, 0x90(%rsp)
leaq 0x127(%rsp), %rdi
movq %rdi, 0x98(%rsp)
callq 0x3470
movq 0x98(%rsp), %rdx
leaq 0x27841(%rip), %rsi     # 0x30770
leaq 0x128(%rsp), %rdi
callq 0x3360
jmp 0x8f3e
movq 0x90(%rsp), %rdi
leaq 0x128(%rsp), %rsi
callq 0x10ad0
jmp 0x8f55
leaq 0x128(%rsp), %rdi
callq 0x31f0
leaq 0x127(%rsp), %rdi
callq 0x3300
leaq 0xf8(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x12000
movq 0x88(%rsp), %rdi
movl $0x2, %esi
callq 0x12010
jmp 0x8f98
movl $0x0, 0xf4(%rsp)
cmpl $0x2, 0xf4(%rsp)
jge 0x90c5
movslq 0xf4(%rsp), %rsi
leaq 0xf8(%rsp), %rdi
callq 0x120b0
movq %rax, %rdi
movl 0x154(%rsp), %eax
incl %eax
movslq %eax, %rsi
callq 0x120d0
jmp 0x8fdc
movl $0x0, 0xf0(%rsp)
movl 0xf0(%rsp), %eax
cmpl 0x154(%rsp), %eax
jg 0x90ad
movslq 0xf4(%rsp), %rsi
leaq 0xf8(%rsp), %rdi
callq 0x120b0
movq %rax, %rdi
movslq 0xf0(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movl 0x154(%rsp), %eax
incl %eax
movslq %eax, %rsi
callq 0x12170
jmp 0x9036
jmp 0x9038
movl 0xf0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf0(%rsp)
jmp 0x8fe7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
jmp 0x9082
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
leaq 0x128(%rsp), %rdi
callq 0x31f0
leaq 0x127(%rsp), %rdi
callq 0x3300
jmp 0x979d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
jmp 0x9790
jmp 0x90af
movl 0xf4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf4(%rsp)
jmp 0x8fa3
movl $0x1, 0xec(%rsp)
movl 0xec(%rsp), %eax
cmpl 0x154(%rsp), %eax
jg 0x924d
movl $0x1, 0xe8(%rsp)
movl 0xe8(%rsp), %eax
cmpl 0x154(%rsp), %eax
jg 0x9235
movl 0xec(%rsp), %eax
cmpl 0xe8(%rsp), %eax
jne 0x914f
leaq 0xf8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xec(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xe8(%rsp), %rsi
callq 0x11720
movl $0x0, (%rax)
jmp 0x921d
movl 0xec(%rsp), %edi
movl 0xe8(%rsp), %esi
movq 0x158(%rsp), %rdx
leaq 0xe4(%rsp), %rcx
callq 0x8df0
movb %al, 0x87(%rsp)
jmp 0x917b
movb 0x87(%rsp), %al
testb $0x1, %al
jne 0x9188
jmp 0x91d2
movl 0xe4(%rsp), %eax
movl %eax, 0x80(%rsp)
leaq 0xf8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xec(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xe8(%rsp), %rsi
callq 0x11720
movl 0x80(%rsp), %ecx
movl %ecx, (%rax)
jmp 0x921b
movl 0xec(%rsp), %eax
cmpl 0xe8(%rsp), %eax
je 0x9219
leaq 0xf8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xec(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xe8(%rsp), %rsi
callq 0x11720
movl $0x3ffffffe, (%rax)     # imm = 0x3FFFFFFE
jmp 0x921b
jmp 0x921d
jmp 0x921f
movl 0xe8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xe8(%rsp)
jmp 0x90ef
jmp 0x9237
movl 0xec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xec(%rsp)
jmp 0x90d0
callq 0x10a60
movq %rax, 0x78(%rsp)
jmp 0x9259
movq 0x78(%rsp), %rdi
callq 0x10b90
jmp 0x9265
callq 0x10a60
movq %rax, 0x70(%rsp)
jmp 0x9271
leaq 0xbf(%rsp), %rdi
movq %rdi, 0x68(%rsp)
callq 0x3470
movq 0x68(%rsp), %rdx
leaq 0x274fb(%rip), %rsi     # 0x3078a
leaq 0xc0(%rsp), %rdi
callq 0x3360
jmp 0x929e
movq 0x70(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x10ad0
jmp 0x92b2
leaq 0xc0(%rsp), %rdi
callq 0x31f0
leaq 0xbf(%rsp), %rdi
callq 0x3300
movl $0x1, 0xb8(%rsp)
movl 0xb8(%rsp), %eax
cmpl 0x154(%rsp), %eax
jg 0x9646
movl $0x1, 0xb4(%rsp)
movl 0xb4(%rsp), %eax
cmpl 0x154(%rsp), %eax
jg 0x962e
movl $0x1, 0xb0(%rsp)
movl 0xb0(%rsp), %eax
cmpl 0x154(%rsp), %eax
jg 0x9509
xorl %eax, %eax
movl %eax, %esi
movq %rsi, 0x48(%rsp)
leaq 0xf8(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x120b0
movq %rax, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xb0(%rsp), %rsi
callq 0x11720
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
movq %rax, 0x50(%rsp)
callq 0x120b0
movq %rax, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xb8(%rsp), %rsi
callq 0x11720
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
movl (%rax), %eax
movl %eax, 0x5c(%rsp)
callq 0x120b0
movq %rax, %rdi
movslq 0xb8(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xb0(%rsp), %rsi
callq 0x11720
movq 0x50(%rsp), %rdi
movq %rax, %rcx
movl 0x5c(%rsp), %eax
movl (%rcx), %ecx
addl %ecx, %eax
movl %eax, 0xac(%rsp)
leaq 0xac(%rsp), %rsi
callq 0x12210
movq %rax, 0x60(%rsp)
jmp 0x93f8
movq 0x60(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x38(%rsp)
leaq 0xf8(%rsp), %rdi
movl $0x1, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xb0(%rsp), %rsi
callq 0x11720
movl 0x38(%rsp), %ecx
movl %ecx, (%rax)
leaq 0xf8(%rsp), %rdi
movl $0x1, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xb0(%rsp), %rsi
callq 0x11720
movl (%rax), %eax
movl %eax, 0x3c(%rsp)
leaq 0xf8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xb0(%rsp), %rsi
callq 0x11720
movl 0x3c(%rsp), %ecx
movl %ecx, (%rax)
movl 0xb0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb0(%rsp)
jmp 0x9315
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
jmp 0x94f7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0x31f0
leaq 0xbf(%rsp), %rdi
callq 0x3300
jmp 0x9790
leaq 0xf8(%rsp), %rdi
movl $0x1, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x11720
cmpl $0x0, (%rax)
jge 0x9616
movq 0x3aa8d(%rip), %rdi     # 0x43fd8
leaq 0x27251(%rip), %rsi     # 0x307a3
callq 0x32c0
movq %rax, 0x30(%rsp)
jmp 0x955e
movq 0x30(%rsp), %rdi
movl 0xb4(%rsp), %esi
callq 0x3440
movq %rax, 0x28(%rsp)
jmp 0x9576
movq 0x28(%rsp), %rdi
leaq 0x2723b(%rip), %rsi     # 0x307bd
callq 0x32c0
movq %rax, 0x20(%rsp)
jmp 0x958e
leaq 0xf8(%rsp), %rdi
movl $0x1, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x11720
movq 0x20(%rsp), %rdi
movl (%rax), %esi
callq 0x3440
movq %rax, 0x18(%rsp)
jmp 0x95d3
movq 0x18(%rsp), %rdi
movq 0x3a9e9(%rip), %rsi     # 0x43fc8
callq 0x32f0
jmp 0x95e6
callq 0x10a60
movq %rax, 0x10(%rsp)
jmp 0x95f2
movq 0x10(%rsp), %rdi
callq 0x10b90
jmp 0x95fe
movb $0x0, 0x167(%rsp)
movl $0x1, 0xa8(%rsp)
jmp 0x9772
jmp 0x9618
movl 0xb4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb4(%rsp)
jmp 0x92f6
jmp 0x9630
movl 0xb8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb8(%rsp)
jmp 0x92d7
callq 0x10a60
movq %rax, 0x8(%rsp)
jmp 0x9652
movq 0x8(%rsp), %rdi
callq 0x10b90
jmp 0x965e
movl $0x1, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
cmpl 0x154(%rsp), %eax
jg 0x975f
movl $0x1, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
cmpl 0x154(%rsp), %eax
jg 0x9747
movl 0xa4(%rsp), %eax
cmpl 0xa0(%rsp), %eax
jne 0x96b1
jmp 0x9731
leaq 0xf8(%rsp), %rdi
movl $0x1, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xa4(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xa0(%rsp), %rsi
callq 0x11720
movl (%rax), %eax
movq 0x148(%rsp), %rcx
cmpl (%rcx), %eax
jge 0x972f
leaq 0xf8(%rsp), %rdi
movl $0x1, %esi
callq 0x120b0
movq %rax, %rdi
movslq 0xa4(%rsp), %rsi
callq 0x11700
movq %rax, %rdi
movslq 0xa0(%rsp), %rsi
callq 0x11720
movl (%rax), %ecx
movq 0x148(%rsp), %rax
movl %ecx, (%rax)
jmp 0x9731
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x9688
jmp 0x9749
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x9669
movb $0x1, 0x167(%rsp)
movl $0x1, 0xa8(%rsp)
leaq 0xf8(%rsp), %rdi
callq 0x12250
movb 0x167(%rsp), %al
andb $0x1, %al
addq $0x168, %rsp            # imm = 0x168
retq
leaq 0xf8(%rsp), %rdi
callq 0x12250
movq 0x118(%rsp), %rdi
callq 0x3460
nopw (%rax,%rax)