// File: Manca[P]algorithms1/./assignment3.hpp
// Function: assignment3::Graph::mincut()
int mincut()
        {
            std::map<int, std::vector<int>> contractedList = adjacencyList; // make a copy of starting list
            size_t n = contractedList.size();
            
            // random generator
            std::random_device rd;
            std::mt19937 gen(rd());
            
            while (n > 2)
            {
                // random vertex from the list of vertices (we know that there are 200 of them,
                // but the correct way should be random vertex from min key to max key
                std::uniform_int_distribution<int> vertexDistribution(1, 200);
                int u = vertexDistribution(gen);

                // if randomly selected u has already been deleted from the list, let's skip it
                if (contractedList.count(u) == 0)
                    continue;
                
                // random edge selection for the given first vertex
                size_t uSize = contractedList[u].size();
                std::uniform_int_distribution<int > edgeDistribution(0, (int)(uSize - 1)); // [a,b]
                int e = edgeDistribution(gen);
                
                // find a node in adjacency list for given vertex represented by e
                int v = contractedList[u].at(e);
                // let's see if the node actually exists in the list
                if (contractedList.count(v) == 0 || u == v)
                    continue;
                
                // merge two nodes into one (we'll use u here and copy all the neighbors of v to u's its adjancency list)
                for (int node : contractedList[v])
                    contractedList[u].push_back(node);
                
                // point other vertices that were pointing to v to u
                for (const auto& map_el : contractedList)
                    for (int& neighbor : contractedList[map_el.first])  // we'll mutate neighbor here
                        if (neighbor == v)
                            neighbor = u;
                
         
                // erase the adjacency list of v and decrease number of nodes by one
                contractedList.erase(v);
                n--;
                
                // finally, let's clean all self loops in a merged node
                size_t i = 0;
                while (i < contractedList[u].size())
                    if (contractedList[u].at(i) == u)
                        contractedList[u].erase(begin(contractedList[u]) + i);
                    else i++;
            }
            
            // last two nodes and their sizes (corresponding to number of crossing edges)
            int u = -1, v = -1;
            size_t uSize = -1, vSize = -1;
            for (const auto& map_el : contractedList)
            {
                if (u == -1)
                {
                    u = map_el.first;
                    uSize = map_el.second.size();
                }
                else
                {
                    v = map_el.first;
                    vSize = map_el.second.size();
                }
            }
            
            // uSize must be the same as vSize
            assert(uSize == vSize);
            
            size_t currentMinCut = uSize;   // either uSize or vSize
            _minCut =  currentMinCut < _minCut ? currentMinCut : _minCut;
            
            return (int)_minCut;
        }

// Assembly:
subq $0x2908, %rsp           # imm = 0x2908
movq %rdi, 0x2900(%rsp)
movq 0x2900(%rsp), %rsi
movq %rsi, 0xa8(%rsp)
leaq 0x28d0(%rsp), %rdi
movq %rdi, 0xb0(%rsp)
callq 0xe100
movq 0xb0(%rsp), %rdi
callq 0x8690
movq %rax, 0x28c8(%rsp)
leaq 0x1540(%rsp), %rdi
callq 0xe130
jmp 0x9998
leaq 0x1540(%rsp), %rdi
callq 0xe1d0
movl %eax, 0xa4(%rsp)
jmp 0x99ae
movl 0xa4(%rsp), %eax
movl %eax, %eax
movl %eax, %esi
leaq 0x1a8(%rsp), %rdi
callq 0xe1e0
jmp 0x99c8
jmp 0x99ca
cmpq $0x2, 0x28c8(%rsp)
jbe 0x9f1e
leaq 0x1a0(%rsp), %rdi
movl $0x1, %esi
movl $0xc8, %edx
callq 0xe210
jmp 0x99f2
leaq 0x1a0(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
callq 0xe240
movl %eax, 0xa0(%rsp)
jmp 0x9a10
movl 0xa0(%rsp), %eax
movl %eax, 0x19c(%rsp)
leaq 0x28d0(%rsp), %rdi
leaq 0x19c(%rsp), %rsi
callq 0x84d0
movq %rax, 0x98(%rsp)
jmp 0x9a3d
movq 0x98(%rsp), %rax
cmpq $0x0, %rax
jne 0x9a8f
jmp 0x99ca
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1538(%rsp)
movl %eax, 0x1534(%rsp)
jmp 0xa0e5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1538(%rsp)
movl %eax, 0x1534(%rsp)
leaq 0x1540(%rsp), %rdi
callq 0xe460
jmp 0xa0e5
leaq 0x28d0(%rsp), %rdi
leaq 0x19c(%rsp), %rsi
callq 0x8530
movq %rax, 0x90(%rsp)
jmp 0x9aae
movq 0x90(%rsp), %rdi
callq 0x7f90
movq %rax, 0x190(%rsp)
movl 0x190(%rsp), %edx
decl %edx
leaq 0x188(%rsp), %rdi
xorl %esi, %esi
callq 0xe210
jmp 0x9add
leaq 0x188(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
callq 0xe240
movl %eax, 0x8c(%rsp)
jmp 0x9afb
movl 0x8c(%rsp), %eax
movl %eax, 0x184(%rsp)
leaq 0x28d0(%rsp), %rdi
leaq 0x19c(%rsp), %rsi
callq 0x8530
movq %rax, 0x80(%rsp)
jmp 0x9b28
movq 0x80(%rsp), %rdi
movslq 0x184(%rsp), %rsi
callq 0xe270
movq %rax, 0x78(%rsp)
jmp 0x9b44
movq 0x78(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x180(%rsp)
leaq 0x28d0(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0x84d0
movq %rax, 0x70(%rsp)
jmp 0x9b6e
movq 0x70(%rsp), %rax
cmpq $0x0, %rax
je 0x9b89
movl 0x19c(%rsp), %eax
cmpl 0x180(%rsp), %eax
jne 0x9b8e
jmp 0x99ca
leaq 0x28d0(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0x8530
movq %rax, 0x68(%rsp)
jmp 0x9baa
movq 0x68(%rsp), %rax
movq %rax, 0x178(%rsp)
movq 0x178(%rsp), %rdi
callq 0x8360
movq %rax, 0x170(%rsp)
movq 0x178(%rsp), %rdi
callq 0x8480
movq %rax, 0x168(%rsp)
leaq 0x170(%rsp), %rdi
leaq 0x168(%rsp), %rsi
callq 0x8620
testb $0x1, %al
jne 0x9bfc
jmp 0x9c53
leaq 0x170(%rsp), %rdi
callq 0x8660
movl (%rax), %eax
movl %eax, 0x164(%rsp)
leaq 0x28d0(%rsp), %rdi
leaq 0x19c(%rsp), %rsi
callq 0x8530
movq %rax, 0x60(%rsp)
jmp 0x9c2e
movq 0x60(%rsp), %rdi
leaq 0x164(%rsp), %rsi
callq 0x7fd0
jmp 0x9c42
jmp 0x9c44
leaq 0x170(%rsp), %rdi
callq 0x8670
jmp 0x9be1
leaq 0x28d0(%rsp), %rax
movq %rax, 0x158(%rsp)
movq 0x158(%rsp), %rdi
callq 0xe2b0
movq %rax, 0x150(%rsp)
movq 0x158(%rsp), %rdi
callq 0xe2e0
movq %rax, 0x148(%rsp)
leaq 0x150(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0xe310
testb $0x1, %al
jne 0x9cab
jmp 0x9d8c
leaq 0x150(%rsp), %rdi
callq 0xe330
movq %rax, 0x140(%rsp)
movq 0x140(%rsp), %rsi
leaq 0x28d0(%rsp), %rdi
callq 0x8530
movq %rax, 0x58(%rsp)
jmp 0x9cdc
movq 0x58(%rsp), %rax
movq %rax, 0x138(%rsp)
movq 0x138(%rsp), %rdi
callq 0x8360
movq %rax, 0x130(%rsp)
movq 0x138(%rsp), %rdi
callq 0x8480
movq %rax, 0x128(%rsp)
leaq 0x130(%rsp), %rdi
leaq 0x128(%rsp), %rsi
callq 0x8620
testb $0x1, %al
jne 0x9d2e
jmp 0x9d78
leaq 0x130(%rsp), %rdi
callq 0x8660
movq %rax, 0x120(%rsp)
movq 0x120(%rsp), %rax
movl (%rax), %eax
cmpl 0x180(%rsp), %eax
jne 0x9d67
movl 0x19c(%rsp), %ecx
movq 0x120(%rsp), %rax
movl %ecx, (%rax)
jmp 0x9d69
leaq 0x130(%rsp), %rdi
callq 0x8670
jmp 0x9d13
jmp 0x9d7a
leaq 0x150(%rsp), %rdi
callq 0xe350
jmp 0x9c8d
leaq 0x28d0(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0xe380
jmp 0x9da3
movq 0x28c8(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x28c8(%rsp)
movq $0x0, 0x118(%rsp)
movq 0x118(%rsp), %rax
movq %rax, 0x48(%rsp)
leaq 0x28d0(%rsp), %rdi
leaq 0x19c(%rsp), %rsi
callq 0x8530
movq %rax, 0x50(%rsp)
jmp 0x9dec
movq 0x50(%rsp), %rdi
callq 0x7f90
movq %rax, %rcx
movq 0x48(%rsp), %rax
cmpq %rcx, %rax
jae 0x9f19
leaq 0x28d0(%rsp), %rdi
leaq 0x19c(%rsp), %rsi
callq 0x8530
movq %rax, 0x40(%rsp)
jmp 0x9e23
movq 0x40(%rsp), %rdi
movq 0x118(%rsp), %rsi
callq 0xe270
movq %rax, 0x38(%rsp)
jmp 0x9e3c
movq 0x38(%rsp), %rax
movl (%rax), %eax
cmpl 0x19c(%rsp), %eax
jne 0x9f00
leaq 0x28d0(%rsp), %rdi
leaq 0x19c(%rsp), %rsi
callq 0x8530
movq %rax, 0x30(%rsp)
jmp 0x9e6c
leaq 0x28d0(%rsp), %rdi
leaq 0x19c(%rsp), %rsi
callq 0x8530
movq %rax, 0x28(%rsp)
jmp 0x9e88
movq 0x28(%rsp), %rdi
callq 0x8910
movq %rax, 0x20(%rsp)
jmp 0x9e99
movq 0x20(%rsp), %rax
movq %rax, 0x100(%rsp)
movq 0x118(%rsp), %rsi
leaq 0x100(%rsp), %rdi
callq 0x8390
movq %rax, 0x108(%rsp)
leaq 0x110(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0xe420
movq 0x30(%rsp), %rdi
movq 0x110(%rsp), %rsi
callq 0xe3b0
movq %rax, 0x18(%rsp)
jmp 0x9ef1
movq 0x18(%rsp), %rax
movq %rax, 0xf8(%rsp)
jmp 0x9f14
movq 0x118(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x118(%rsp)
jmp 0x9dc3
jmp 0x99ca
movl $0xffffffff, 0xf4(%rsp) # imm = 0xFFFFFFFF
movl $0xffffffff, 0xf0(%rsp) # imm = 0xFFFFFFFF
movq $-0x1, 0xe8(%rsp)
movq $-0x1, 0xe0(%rsp)
leaq 0x28d0(%rsp), %rax
movq %rax, 0xd8(%rsp)
movq 0xd8(%rsp), %rdi
callq 0xe2b0
movq %rax, 0xd0(%rsp)
movq 0xd8(%rsp), %rdi
callq 0xe2e0
movq %rax, 0xc8(%rsp)
leaq 0xd0(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0xe310
testb $0x1, %al
jne 0x9fa4
jmp 0xa02d
leaq 0xd0(%rsp), %rdi
callq 0xe330
movq %rax, 0xc0(%rsp)
cmpl $-0x1, 0xf4(%rsp)
jne 0x9fef
movq 0xc0(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xf4(%rsp)
movq 0xc0(%rsp), %rdi
addq $0x8, %rdi
callq 0x7f90
movq %rax, 0xe8(%rsp)
jmp 0xa019
movq 0xc0(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xf0(%rsp)
movq 0xc0(%rsp), %rdi
addq $0x8, %rdi
callq 0x7f90
movq %rax, 0xe0(%rsp)
jmp 0xa01b
leaq 0xd0(%rsp), %rdi
callq 0xe350
jmp 0x9f86
movq 0xe8(%rsp), %rax
cmpq 0xe0(%rsp), %rax
jne 0xa041
jmp 0xa060
leaq 0x1074f(%rip), %rdi     # 0x1a797
leaq 0x10757(%rip), %rsi     # 0x1a7a6
movl $0xa4, %edx
leaq 0x1075d(%rip), %rcx     # 0x1a7b8
callq 0x2140
movq 0xa8(%rsp), %rcx
movq 0xe8(%rsp), %rax
movq %rax, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
cmpq 0x30(%rcx), %rax
jae 0xa095
movq 0xb8(%rsp), %rax
movq %rax, 0x10(%rsp)
jmp 0xa0a6
movq 0xa8(%rsp), %rax
movq 0x30(%rax), %rax
movq %rax, 0x10(%rsp)
movq 0xa8(%rsp), %rax
movq 0x10(%rsp), %rcx
movq %rcx, 0x30(%rax)
movq 0x30(%rax), %rax
movl %eax, 0xc(%rsp)
leaq 0x1540(%rsp), %rdi
callq 0xe460
leaq 0x28d0(%rsp), %rdi
callq 0x8860
movl 0xc(%rsp), %eax
addq $0x2908, %rsp           # imm = 0x2908
retq
leaq 0x28d0(%rsp), %rdi
callq 0x8860
movq 0x1538(%rsp), %rdi
callq 0x2330
nop