Cod sursa(job #2821501)

Utilizator 6kmeleon6Luca Cordus 6kmeleon6 Data 22 decembrie 2021 17:37:24
Problema Algoritmul lui Dijkstra Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 9.86 kb
#include <bits/stdc++.h>
#include <limits>

using namespace std;

int infinit = std::numeric_limits<int>::max();

/*
/// FISIERE BFS
ifstream in("bfs.in");
ofstream out("bfs.out");

/// FISIERE DFS
ifstream in("dfs.in");
ofstream out("dfs.out");

/// FISIERE BICONEX
ifstream in("biconex.in");
ofstream out("biconex.out");

/// FISIERE CTC
ifstream in("ctc.in");
ofstream out("ctc.out");

/// FISIERE SORTARET
ifstream in("sortaret.in");
ofstream out("sortaret.out");

/// FISIERE CC
ifstream in("cc.in");
ofstream out("cc.out");
*/
/// FISIERE DIJKSTRA
ifstream in("dijkstra.in");
ofstream out("dijkstra.out");

class Graf
{
    int nr_N, nr_M, S;
    vector<vector<int>> adiac, GT; /// GT = GRAF TRANSPUS(PENTRU CTC)

public:

    /// Constructori
    Graf() : nr_N(0), nr_M(0) {}
    Graf(int N, int M) : nr_N(N), nr_M(M) {}

    void citire_or();
    void citire_neor();
    void citire_or_CTC();
    void citire_or_costuri(vector<vector<pair<int,int>>>&);

    void BFS();

    void conexe();

    void nma_nivel(int, int, vector<vector<int>>&, vector<int>&, vector<int>&, stack<int>&, int&, vector<int>&);
    void Biconex();

    void CTC();
    void DFS_adiac_CTC(int, vector<int>&, vector<bool>&);
    void DFS_GT_CTC(int, vector<bool>&, vector<vector<int>>&, int&);

    void SortareT();

    void nma_nivel_CC(int, int, vector<int>&, vector<int>&, int&, vector<int>&);
    void CC();

    void Dijkstra();
};

void Graf::citire_or()  /// CITIRE GRAF ORIENTAT
{
    in >> nr_N >> nr_M >> S;
    adiac = vector<vector<int>>(nr_N + 1);
    for (int i = 0; i < nr_M; i++)
    {
        int x, y;
        in >> x >> y;
        adiac[x].push_back(y);
    }
}

void Graf::citire_or_CTC()  /// CITIRE GRAF ORIENTAT PENTRU CTC
{
    in >> nr_N >> nr_M;
    adiac = GT = vector<vector<int>>(nr_N + 1);
    for (int i = 0; i < nr_M; i++)
    {
        int x, y;
        in >> x >> y;
        adiac[x].push_back(y);
        GT[y].push_back(x);
    }
}

void Graf::citire_neor()    /// CITIRE GRAF NEORIENTAT
{
    in >> nr_N >> nr_M;
    adiac = vector<vector<int>>(nr_N + 1);
    for (int i = 0; i < nr_M; i++)
    {
        int x, y;
        in >> x >> y;
        adiac[x].push_back(y);
        adiac[y].push_back(x);
    }
}

void Graf::citire_or_costuri(vector<vector<pair<int,int>>>& costuri)
{
    in >> nr_N >> nr_M;
    costuri = vector<vector<pair<int,int>>>(nr_N + 1);
    for(int i = 1; i <= nr_M; i++)
    {
        int x, y, c;
        in >> x >> y >> c;
        costuri[x].push_back({y,c}); /// Muchia de la x plecand in y are costul c
    }
}
void Graf::BFS() /// BFS
{
    queue <int> coada;
    int nod;
    int vizitat[100001] = {};
    vizitat[S] = 1;
    coada.push(S);
    int cost[100001] = {};
    cost[S] = 0;///Costul la nodul de start este 0

    while(coada.size() > 0) ///Cat timp inca mai am noduri in graf
    {
        nod = coada.front();

        for(int j = 0; j < adiac[nod].size(); j++)
        {
            if(vizitat[adiac[nod][j]] == 0)
            {
                coada.push(adiac[nod][j]);
                cost[adiac[nod][j]] = cost[nod] + 1;
                vizitat[adiac[nod][j]]++;
            }
        }
        coada.pop();
    }

    for(int i = 1; i <= nr_N; i++)
    {
        if(vizitat[i] == 0) out << "-1 ";
        else out << cost[i] << " ";
    }
}

void Graf::conexe() /// NUMARARE COMPONENTE CONEXE PENTRU DFS
{
    vector<int> stiva;
    vector<bool> vizitat;
    vizitat = vector<bool> (nr_N + 1, false);
    int nr=0, i;

    for(int i = 1; i <= nr_N; i++)
    {
        if(!vizitat[i])
        {
            DFS_adiac_CTC(i, stiva, vizitat);
            nr++;
        }
    }

    out << nr;
}

void Graf::nma_nivel(int k, int tata, vector<vector<int>>& componente_bi, vector<int>& nma, vector<int>& nivel, stack<int>& stiva, int& nr, vector<int>& V) /// BICONEX_DFS
{
    V[k] = 1;
    stiva.push(k);
    nivel[k] = nivel[tata] + 1;
    nma[k] = nivel[k];
    for(int i = 0; i < adiac[k].size(); i++)
    {
        int x = adiac[k][i];
        ///cout << "test ";
        if(x != tata)
        {
            if(V[x] == 1)
            {
                ///cout << k << " " << adiac[k][i] << " | ";
                if(nma[k] > nivel[x])
                    nma[k] = nma[x];
            }
            else
            {
                nma_nivel(adiac[k][i], k, componente_bi, nma, nivel, stiva, nr, V);
                if(nma[k] > nma[x])
                {
                    nma[k] = nma[adiac[k][i]];
                }
                if(nivel[k] <= nma[x])
                {
                    ///cout << k << " " << adiac[k][i] << " | ";
                    while (stiva.top() != x)
                    {
                        componente_bi[nr].push_back(stiva.top());
                        stiva.pop();
                    }
                    componente_bi[nr].push_back(x);
                    stiva.pop();
                    componente_bi[nr].push_back(k);
                    nr++;
                }
            }
        }
    }
}

void Graf::Biconex() /// BICONEX
{
    vector<vector<int>> componente_bi;
    componente_bi.resize(nr_N + 1);
    vector<int> nma(nr_N + 1), nivel(nr_N + 1), V(nr_N + 1);
    int nr = 0;
    stack<int> stiva;
    ///cout << "test";
    nma_nivel(1, 0, componente_bi, nma, nivel, stiva, nr, V);
    ///cout << "TEST";
    out << nr << '\n';
    for(int i = 0; i < nr; i++)
    {
        for(int j = 0; j < componente_bi[i].size(); j++)
        {
            out << componente_bi[i][j] << " ";
        }
        out << '\n';
    }
}

void Graf::DFS_adiac_CTC(int k, vector<int>& stiva_CTC, vector<bool>& V_CTC) /// Sortare Topologica
{
    V_CTC[k] = true;
    for(auto x : adiac[k])
        if(!V_CTC[x])
            DFS_adiac_CTC(x, stiva_CTC, V_CTC);
    stiva_CTC.push_back(k);
}

void Graf::DFS_GT_CTC(int k, vector<bool>& V_CTC, vector<vector<int>>& componente_tc, int& contor)
{
    V_CTC[k] = true;
    for(auto x : GT[k])
        if(!V_CTC[x])
            DFS_GT_CTC(x, V_CTC, componente_tc, contor);
    componente_tc[contor].push_back(k);
}

void Graf::CTC() /// CTC
{
    vector<vector<int>> componente_tc;
    componente_tc.resize(nr_N + 1);
    vector<int> stiva_CTC;
    vector<bool> V_CTC;
    int nr = 0;
    V_CTC = vector<bool> (nr_N + 1, false);
    for(int i = 1; i <= nr_N; i++)
    {
        if(!V_CTC[i])
            DFS_adiac_CTC(i, stiva_CTC, V_CTC);
    }
    V_CTC = vector<bool> (nr_N + 1, false);
    for(vector<int>::reverse_iterator it = stiva_CTC.rbegin() ; it != stiva_CTC.rend() ; it ++)
        if(!V_CTC[*it])
        {
            nr++;
            DFS_GT_CTC(*it, V_CTC, componente_tc, nr);
        }
    out << nr << '\n';
    for(int i = 0; i <= nr_N; i++)
    {
        if(componente_tc[i].size() >= 1)
        {
            for(int j = 0; j <componente_tc[i].size(); j++)
            {
                out << componente_tc[i][j] << " ";
            }
            out << '\n';
        }
    }
}

void Graf::SortareT() /// SORTARET
{
    vector<int> stiva_ST;
    vector<bool> V_ST;
    V_ST = vector<bool> (nr_N + 1, false);
    for(int i = 1; i <= nr_N; i++)
    {
        if(V_ST[i] == false)
            DFS_adiac_CTC(i, stiva_ST, V_ST);
    }

    for(int i = stiva_ST.size() - 1; i >= 0; i--)
        out << stiva_ST[i] << " ";
}

void Graf::nma_nivel_CC(int k, int tata, vector<int>& nma, vector<int>& nivel, int& nr, vector<int>& V) /// Critical connections
{

    V[k] = 1;
    nivel[k] = nivel[tata] + 1;
    nma[k] = nivel[k];
    for(int i = 0; i < adiac[k].size(); i++)
    {
        int x = adiac[k][i];
        ///cout << "test ";
        if(x != tata)
        {
            if(V[x] == 1)
            {
                ///cout << k << " " << adiac[k][i] << " | ";
                if(nma[k] > nivel[x])
                    nma[k] = nma[x];
            }
            else
            {
                nma_nivel_CC(adiac[k][i], k, nma, nivel, nr, V);
                if(nma[k] > nma[x])
                {
                    nma[k] = nma[x];
                }
                if(nivel[k] < nma[x])
                    out << "[" << k << ", " << x << "] ";
            }
        }
    }
}

void Graf::CC()
{
    vector<int> nma(nr_N + 1), nivel(nr_N + 1), V(nr_N + 1);
    int nr = 0;
    stack<int> stiva;
    nma_nivel_CC(1, 0, nma, nivel, nr, V);
}

void Graf::Dijkstra()
{
    vector<vector<pair<int,int>>> costuri;
    int V[100001], dist[100001];
    citire_or_costuri(costuri);

    for(int i = 1; i <= nr_N; i++)
        dist[i] = infinit;

    dist[1]=0;

    priority_queue<pair<int,int>> H; /// Va sorta singur in functie de cea mai mica distanta
    H.push({0,1});

    while(H.size() > 0)
    {

        int u = H.top().second;
        H.pop();
        if(V[u])
            continue;
        else
            V[u]++;
        for(auto v : costuri[u]) /// Verificam toti vecinii lui u
        {
            if(dist[v.first] > dist[u] + v.second)
            {
                dist[v.first] = dist[u] + v.second;
                H.push({-dist[v.first], v.first}); /// Folosim -dist[v.first] ca sa avem in top cea mai mica valoare
            }
        }
    }

    for(int i = 2; i <= nr_N; i++)
    {
        if(dist[i] != infinit)
            out << dist[i] << " ";
        else
            out << "0 ";
    }
}
int main()
{
    Graf G;
    /*
    ///BFS
    G.citire_or();
    G.BFS();

    ///DFS
    G.citire_neor();
    G.conexe();

    ///Biconex
    G.citire_neor();
    G.Biconex();
    ///CTC
    G.citire_or_CTC();
    G.CTC();

    ///SortareT
    G.citire_or_CTC();
    G.SortareT();

    ///CCIN
    G.citire_neor();
    G.CC();
    */
    /// Dijkstra
    G.Dijkstra();

    return 0;
}