Cod sursa(job #2822086)

Utilizator Teodora11faranume Teodora11 Data 23 decembrie 2021 15:41:38
Problema Parcurgere DFS - componente conexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 17.24 kb
#include <algorithm>
#include <climits>
#include <fstream>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>

using namespace std;

class Algorithms
{
private:
    Algorithms()
    {}

public:
    static void DFS( const vector<vector<int>> &adjacencyList, int startNode, vector<bool> &visited )
    {
        stack<int> nodes;
        nodes.push( startNode );

        while( !nodes.empty() )
        {
            int crtNode = nodes.top();
            nodes.pop();

            if( visited[crtNode] )
                continue;

            visited[crtNode] = true;
            for( auto node : adjacencyList[crtNode] )
            {
                if( !visited[node] )
                    nodes.push( node );
            }
        }
    }

    static void BFS( const vector<vector<int>> &adjacencyList, int startNode, vector<int> &distance )
    {
        queue<pair<int, int>> nodes;
        nodes.push( { startNode, 0 } );
        distance[startNode] = 0;

        while( !nodes.empty() )
        {
            int crtNode = nodes.front().first, crtDistance = nodes.front().second;
            nodes.pop();

            for( auto node : adjacencyList[crtNode] )
            {
                if( distance[node] == -1 )
                {
                    distance[node] = crtDistance + 1;
                    nodes.push( { node, distance[node] } );
                }
            }
        }
    }

    static vector<vector<int>> getComponenteBiconexe( const vector<vector<int>> &adjacencyList, int n )
    {
        vector<bool>        visited( n + 1 );
        vector<int>         levels( n + 1 );
        vector<int>         minLevels( n + 1 );
        vector<vector<int>> componenteBiconexe;
        stack<int>          componenta;
        for( int i = 1; i < adjacencyList.size(); ++i )
        {
            componenteBiconexeHelper( adjacencyList, i, 0, 0, levels, minLevels, visited, componenta,
                                      componenteBiconexe );
        }

        return componenteBiconexe;
    }

    static vector<vector<int>> getComponenteTareConexe( const vector<vector<int>> &adjacencyList, int n,
                            const vector<vector<int>> &transposeList )
    {
        vector<bool> visited( n + 1 );
        stack<int>   traversal;
        for( int i = 1; i <= n; ++i )
            if( !visited[i] )
                componenteTareConexeHelper( adjacencyList, i, visited, traversal );

        vector<vector<int>> componente;
        for( ; !traversal.empty(); traversal.pop() )
        {
            int x = traversal.top();
            if( visited[x] )
            {
                componente.push_back( vector<int>() );
                componenteTareConexeHelperTranspose( transposeList, x, visited, componente.back() );
            }
        }

        return componente;
    }

    static vector<int> getDijkstra( const vector<vector<pair<int, int>>> &adjacencyList, int n, int m )
    {
        vector<int> d( n + 1, INT_MAX ), visited( n + 1 );
        d[1] = 0;
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
        q.push( { 0, 1 } );
        while( !q.empty() )
        {
            int node = q.top().second;
            q.pop();
            if( visited[node] )
                continue;

            visited[node] = true;
            for( auto neighbour : adjacencyList[node] )
            {
                if( d[node] + neighbour.second < d[neighbour.first] )
                {
                    d[neighbour.first] = d[node] + neighbour.second;
                    q.push( { d[neighbour.first], neighbour.first } );
                }
            }
        }

        return d;
    }

    static vector<int> getBellmanFord( const vector<vector<pair<int, int>>> &adjacencyList, int n, int m )
    {
        vector<int> d( n + 1, INT_MAX ), visited( n + 1 );
        d[1] = 0;
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
        q.push( { 0, 1 } );
        while( !q.empty() )
        {
            int node = q.top().second;
            q.pop();
            visited[node]++;
            if( visited[node] >= n )
            {
                d.resize( 0 );
                break;
            }

            for( auto neighbour : adjacencyList[node] )
                if( d[node] + neighbour.second < d[neighbour.first] )
                {
                    d[neighbour.first] = d[node] + neighbour.second;
                    q.push( make_pair( d[neighbour.first], neighbour.first ) );
                }
        }

        return d;
    }

    static void getRoyFloyd( int n, vector<vector<int>> &costMatrix )
    {
        for( int k = 1; k <= n; k++ )
            for( int i = 1; i <= n; i++ )
                for( int j = 1; j <= n; j++ )
                    if( i != j && costMatrix[i][k] != 0 && costMatrix[k][j] != 0 &&
                            ( costMatrix[i][j] > costMatrix[i][k] + costMatrix[k][j] || costMatrix[i][j] == 0 ) )
                        costMatrix[i][j] = costMatrix[i][k] + costMatrix[k][j];
    }

    static int findRoot( int node, vector<int> &t )
    {
        if( t[node] == node )
            return node;

        t[node] = findRoot( t[node], t );

        return t[node];
    }

    static void unite( int node1, int node2, vector<int> &t )
    {
        t[Algorithms::findRoot( node2, t )] = Algorithms::findRoot( node1, t );
    }

    static int getDiameter( const vector<vector<int>> &adjacencyList, int n )
    {
        int         maxDistance = -1, furthestNode, furthestNode2;
        vector<int> distance( n + 1, -1 );

        Algorithms::BFS( adjacencyList, 1, distance );

        for( int i = 1; i <= n; ++i )
        {
            if( distance[i] > maxDistance )
            {
                maxDistance  = distance[i];
                furthestNode = i;
            }
        }

        fill( distance.begin(), distance.end(), -1 );  // reinitializez distanta la -1

        Algorithms::BFS( adjacencyList, furthestNode, distance );

        maxDistance = -1;
        for( int i = 1; i <= n; ++i )
        {
            if( distance[i] > maxDistance )
            {
                maxDistance = distance[i];
            }
        }

        return maxDistance + 1;
    }

    static vector<int> sortTopological( const vector<vector<int>> &adjacencyList, int n )
    {
        vector<bool> visited( n + 1 );
        stack<int>   traversal;
        Algorithms::sortTopologicalHelper( adjacencyList, 1, visited, traversal );

        vector<int> sorted;
        while( !traversal.empty() )
        {
            sorted.push_back( traversal.top() );
            traversal.pop();
        }

        return sorted;
    }

    static vector<vector<int>> havelHakimi( vector<int> &v, int n )
    {
        vector<vector<int>> adjacencyList( n + 1 );
        int                 crtFirst = 1;  // primul element nenul
        while( true )
        {
            int i;
            for( i = crtFirst + 1; i < v.size(); ++i )
            {
                v[i] -= v[crtFirst];
                --v[crtFirst];

                adjacencyList[crtFirst].push_back( i );
            }

            if( v[crtFirst] > 0 )
            {
                return vector<vector<int>>();
            }

            sort( v.begin() + crtFirst, v.begin() + n + 1, less<int>() );

            while( v[crtFirst] == 0 )
                ++crtFirst;

            reverse( v.begin() + crtFirst, v.begin() + n + 1 );

            if( v[n] == 0 )
            {
                return adjacencyList;
            }
        }
    }

private:
    static void componenteBiconexeHelper( const vector<vector<int>> &adjacencyList, int crtNode, int parent,
                                          int crtLevel, vector<int> &levels, vector<int> &minLevels,
                                          vector<bool> &visited, stack<int> &componenta,
                                          vector<vector<int>> &componenteBiconexe )
    {
        visited[crtNode]   = true;
        levels[crtNode]    = crtLevel;
        minLevels[crtNode] = crtLevel;
        componenta.push( crtNode );

        for( auto node : adjacencyList[crtNode] )
        {
            if( !visited[node] )
            {
                int capNode = componenta.top();

                componenteBiconexeHelper( adjacencyList, node, crtNode, crtLevel + 1, levels, minLevels, visited,
                                          componenta, componenteBiconexe );

                if( minLevels[node] >= levels[crtNode] || ( parent == 0 && adjacencyList[crtNode].size() > 1 ) )
                {
                    componenteBiconexe.push_back( vector<int>( { crtNode } ) );
                    while( componenta.top() != capNode )
                    {
                        componenteBiconexe.back().push_back( componenta.top() );
                        componenta.pop();
                    }
                }

                minLevels[crtNode] = min( minLevels[crtNode], minLevels[node] );
            }
            else if( node != parent )
                minLevels[crtNode] = min( minLevels[crtNode], levels[node] );
        }
    }

    static void componenteTareConexeHelper( const vector<vector<int>> &adjacencyList, int crtNode,
                                            vector<bool> &visited, stack<int> &traversal )
    {
        visited[crtNode] = true;
        for( auto node : adjacencyList[crtNode] )
            if( !visited[node] )
                componenteTareConexeHelper( adjacencyList, node, visited, traversal );

        traversal.push( crtNode );
    }

    static void componenteTareConexeHelperTranspose( const vector<vector<int>> &adjacencyList, int crtNode,
            vector<bool> &visited, vector<int> &componenta )
    {
        visited[crtNode] = false;
        componenta.push_back( crtNode );
        for( auto node : adjacencyList[crtNode] )
            if( visited[node] )
                componenteTareConexeHelperTranspose( adjacencyList, node, visited, componenta );
    }

    static void sortTopologicalHelper( const vector<vector<int>> &adjacencyList, int crtNode, vector<bool> &visited,
                                       stack<int> &traversal )
    {
        visited[crtNode] = true;
        for( auto node : adjacencyList[crtNode] )
            if( !visited[node] )
                sortTopologicalHelper( adjacencyList, node, visited, traversal );

        traversal.push( crtNode );
    }
};

void solveDFS()
{
    int      n, m;
    ifstream in( "dfs.in" );
    in >> n >> m;
    vector<vector<int>> adjacencyList( n + 1 );

    int x, y;
    for( int i = 0; i < m; ++i )
    {
        in >> x >> y;
        adjacencyList[x].push_back( y );
        adjacencyList[y].push_back( x );
    }

    int          nrComponents = 0;
    vector<bool> visited( n + 1 );
    ofstream     out( "dfs.out" );
    for( int startNode = 1; startNode <= n; ++startNode )
        if( !visited[startNode] )
        {
            ++nrComponents;
            Algorithms::DFS( adjacencyList, startNode, visited );
        }

    out << nrComponents;
}

void solveBFS()
{
    int      n, m, S;
    ifstream in( "bfs.in" );
    in >> n >> m >> S;
    vector<vector<int>> adjacencyList( n + 1 );

    int x, y;
    for( int i = 0; i < m; ++i )
    {
        in >> x >> y;
        adjacencyList[x].push_back( y );
    }

    vector<int> distance( n + 1, -1 );
    ofstream    out( "bfs.out" );
    Algorithms::BFS( adjacencyList, S, distance );
    for( int i = 1; i <= n; ++i )
    {
        out << distance[i] << ' ';
    }
}

void solveBiconex()
{
    int      n, m;
    ifstream in( "biconex.in" );
    in >> n >> m;
    vector<vector<int>> adjacencyList( n + 1 );

    int x, y;
    for( int i = 0; i < m; ++i )
    {
        in >> x >> y;
        adjacencyList[x].push_back( y );
        adjacencyList[y].push_back( x );
    }

    // dintr-un descdendent cu un back-edge
    vector<vector<int>> componenteBiconexe = Algorithms::getComponenteBiconexe( adjacencyList, n );

    ofstream out( "biconex.out" );
    out << componenteBiconexe.size() << '\n';
    for( const auto &componenta : componenteBiconexe )
    {
        for( auto node : componenta )
            out << node << ' ';
        out << '\n';
    }
}

void solveTareConex()
{
    int      n, m;
    ifstream in( "ctc.in" );
    in >> n >> m;
    vector<vector<int>> adjacencyList( n + 1 );
    vector<vector<int>> transposeList( n + 1 );

    int x, y;
    for( int i = 0; i < m; ++i )
    {
        in >> x >> y;
        adjacencyList[x].push_back( y );
        transposeList[y].push_back( x );
    }

    vector<vector<int>> componenteTareConexe = Algorithms::getComponenteTareConexe( adjacencyList, n, transposeList );

    ofstream out( "ctc.out" );
    out << componenteTareConexe.size() << '\n';
    for( const auto &componenta : componenteTareConexe )
    {
        for( auto node : componenta )
            out << node << ' ';
        out << '\n';
    }
}

void solveDijkstra()
{
    int      n, m;
    ifstream in( "dijkstra.in" );
    ofstream out( "dijkstra.out" );
    in >> n >> m;
    vector<vector<pair<int, int>>> v( n + 1 );
    for( int i = 1; i <= m; i++ )
    {
        int x, y, cost;
        in >> x >> y >> cost;
        v[x].push_back( make_pair( y, cost ) );
    }
    vector<int> dijkstra = Algorithms::getDijkstra( v, n, m );
    for( int i = 2; i <= n; i++ )
    {
        if( dijkstra[i] == INT_MAX )
            out << "0 ";
        else
            out << dijkstra[i] << ' ';
    }
}

void solveBellmanFord()
{
    int      n, m;
    ifstream in( "bellmanford.in" );
    ofstream out( "bellmanford.out" );
    in >> n >> m;
    vector<vector<pair<int, int>>> v( n + 1 );
    for( int i = 1; i <= m; i++ )
    {
        int x, y, cost;
        in >> x >> y >> cost;
        v[x].push_back( make_pair( y, cost ) );
    }
    vector<int> bellmanFord = Algorithms::getBellmanFord( v, n, m );
    if( bellmanFord.size() != 0 )
    {
        for( int i = 2; i <= n; i++ )
        {
            if( bellmanFord[i] == INT_MAX )
                out << "0 ";
            else
                out << bellmanFord[i] << ' ';
        }
    }
    else
        out << "Ciclu negativ!";
}

void solveDisjoint()
{
    ifstream in( "disjoint.in" );
    ofstream out( "disjoint.out" );
    int      k, x, y, n, m;
    in >> n >> m;

    vector<int> t( n + 1 );
    for( int i = 1; i <= n; i++ )
        t[i] = i;

    for( int i = 1; i <= m; i++ )
    {
        in >> k >> x >> y;
        if( k == 1 )
            Algorithms::unite( x, y, t );
        else
        {
            if( Algorithms::findRoot( x, t ) == Algorithms::findRoot( y, t ) )
                out << "DA\n";
            else
                out << "NU\n";
        }
    }
}

void solveDarb()
{
    ifstream in( "darb.in" );
    int      n;
    in >> n;
    vector<vector<int>> adjacencyList( n + 1 );

    for( int i = 0; i < n - 1; ++i )
    {
        int x, y;
        in >> x >> y;
        adjacencyList[x].push_back( y );
        adjacencyList[y].push_back( x );
    }

    ofstream out( "darb.out" );
    out << Algorithms::getDiameter( adjacencyList, n );
}

void solveRoyFloyd()
{
    ifstream in( "royfloyd.in" );
    int      n;
    in >> n;
    vector<vector<int>> costMatrix( n + 1,
                                    vector<int>( n + 1 ) );

    for( int i = 1; i <= n; i++ )
        for( int j = 1; j <= n; j++ )
            in >> costMatrix[i][j];

    Algorithms::getRoyFloyd( n, costMatrix );

    ofstream out( "royfloyd.out" );
    for( int i = 1; i <= n; i++ )
    {
        for( int j = 1; j <= n; j++ )
            out << costMatrix[i][j] << " ";
        out << endl;
    }
}

void solveSortTopological()
{
    ifstream in( "sortaret.in" );
    int      n, m;
    in >> n >> m;
    vector<vector<int>> adjacencyList( n + 1 );

    int x, y;
    for( int i = 0; i < m; ++i )
    {
        in >> x >> y;
        adjacencyList[x].push_back( y );
    }

    vector<int> sorted = Algorithms::sortTopological( adjacencyList, n );

    ofstream out( "sortaret.out" );
    for( auto node : sorted )
    {
        out << node << ' ';
    }
}

void solveHavelHakimi()
{
    int      n;
    ifstream in( "hakimi.in" );
    in >> n;
    vector<int> v( n + 1 );

    for( int i = 1; i <= n; ++i )
    {
        in >> v[i];
    }

    auto adjacencyList = Algorithms::havelHakimi( v, n );

    ofstream out( "hakimi.out" );
    if( adjacencyList.size() == 0 )
    {
        out << "imposibil\n";
    }
    else
    {
        for( int i = 1; i <= n; ++i )
        {
            for( auto node : adjacencyList[i] )
            {
                out << i << ' ' << node << '\n';
            }
        }
    }
}

int main()
{
    solveDFS();
    // solveBFS();
    // solveBiconex();
    // solveTareConex();
    // solveDijkstra();
    // solveBellmanFord();
    // solveDisjoint();
    // solveDarb();
    // solveRoyFloyd();
    // solveSortTopological();
    // solveHavelHakimi();
}