Cod sursa(job #2754749)

Utilizator PopelEmilBogdanPopel Emil-Bogdan PopelEmilBogdan Data 26 mai 2021 14:46:02
Problema Heapuri cu reuniune Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.32 kb
#include <bits/stdc++.h>

using namespace std;

template <class T>
class node
{
public:
    T value;
    node * left, *right, *parent, *child;
    int degree;

    node()
    {
        left = NULL;
        right = NULL;
        parent = NULL;
        child = NULL;
        degree = 0;
    }
};

template <class T>
class FibonacciHeap
{
public:
    int size;
    node<T>* mini;

    FibonacciHeap<T>()
    {
        this -> size = 0;
        this -> mini = NULL;
    }

    void Insert(T val)
    {
        size++;
        node<T>* new_node = new node<T>;
        new_node->value = val;
        new_node->left = new_node;
        new_node->right = new_node;
        if (mini == NULL)
        {
            mini = new_node;
            return;
        }

        (mini->left)->right = new_node;
        new_node->right = mini;
        new_node->left = mini->left;
        mini->left = new_node;

        if (mini->value < val) // actualizam minimul
            mini = new_node;
    }

    T GetMini()
    {
         return mini->value;
    }

    void Cut_Parent_links(node<T>* curr)
    {
        if (curr == NULL)
            return;

        node<T> * aux = curr;
        do
        {
            aux->parent = NULL;
            aux = aux -> right;
        }while (aux != curr);
    }

    void Cut_Sides(node<T>* curr)
    {
        if (curr -> right == curr)
            return;

        node<T>* toLeft = curr ->left;
        node<T> * toRight = curr -> right;

        toLeft->right = toLeft;
        toRight->left = toRight;
    }

    node<T>* Merge(node<T>* node1, node<T>* node2)
    {
        if (node1 == NULL) return node2;
        if (node2 == NULL) return node1;

        if (node1->value < node2->value)
        {
            node<T>* aux = node2;
            node2 = node1;
            node1 = aux;
        }

        node<T>* right1 = node1 -> right;
        node<T>* left2 = node2 -> left;
        node1->right = node2;
        node2->left = node1;

        right1->left = left2;
        left2->right = right1;
        return node1;
    }

    void Add_child(node<T>* Nodparinte, node<T>* new_child)
    {
        this->Cut_Sides(new_child);
        new_child->left = new_child -> right = new_child;
        new_child->parent = Nodparinte;
        Nodparinte -> child = Merge(Nodparinte->child, new_child);
        Nodparinte ->degree += 1;
    }


    void _consolidate()
    {
        int dimension = (int) (log(size)/ log(2)); //every node has degree at most log n - Wikipedia
        node<T>* Degrees[dimension + 1];

        for (int i = 0; i < dimension + 1; ++i)
            Degrees[i] =  NULL;

        node<T>* itr = mini;
        bool flag = 0;
        int curr_degree;
        do
        {

            curr_degree = itr -> degree;
            while(Degrees[curr_degree] != NULL)
            {
                node<T> *p = Degrees[curr_degree];
                if (p == itr)
                {
                    flag = 1;
                    break;
                }

                if (itr -> value < p -> value)
                {
                    node<T>* aux = p;
                    p = itr;
                    itr = aux;
                }

                this->Add_child(itr, p);
                Degrees[curr_degree] = NULL;
                curr_degree+=1;
            }

            if (flag) break;

            Degrees[itr -> degree] = itr;
            itr = itr -> left;
        }while (true);

        mini = NULL;
        node<T>* stop = itr;
        do
        {
            if (mini == NULL || itr -> value < mini -> value)
                mini = itr;
            itr = itr -> left;
        }while (itr != stop);
    }

    node<T>* _deleteMin()
    {
        if (mini == NULL)
            return NULL;

        node<T> *aux = mini;
        this->Cut_Parent_links(aux->child);
        this ->Merge(aux, aux->child);
        this -> Cut_Sides(aux);
        size --;

        if (aux == aux ->right )
            mini = NULL;
        else
        {
            mini = aux -> right;
            this -> _consolidate();
        }
        return aux;
    }

    void mergeHeaps(FibonacciHeap& otherheap)
    {
        mini = this->Merge(mini, otherheap.mini);
        size += otherheap.size;
        otherheap.size = 0;
        otherheap.mini = NULL;
    }
};


int main()
{

    ifstream fin("mergeheap.in");
    ofstream fout("mergeheap.out");
    int N, K, type, where, who;
    fin >> N >> K;
    vector<FibonacciHeap<int>> multimi;
    for (int i = 0; i < N; ++i)
        multimi.push_back(FibonacciHeap<int>());
    for (; K > 0; K--)
    {
        fin >> type;
        switch(type)
        {
        case 1:
            {
                fin >> where >> who;
                multimi[where - 1].Insert(who);;
                break;
            }
        case 2:
            {
                fin >> where;
                fout << multimi[where - 1].GetMini() << "\n";
                multimi[where - 1]._deleteMin();
                break;
            }
        case 3:
            {
                fin >> where >> who;
                multimi[where - 1].mergeHeaps(multimi[who - 1]);
                break;
            }
        }
    }

    return 0;
}