Cod sursa(job #2798892)

Utilizator StefaniaCriStefania Cristea StefaniaCri Data 12 noiembrie 2021 00:57:45
Problema Componente tare conexe Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 9.69 kb
#include <iostream>
#include <vector>
#include <queue>
#include <fstream>
#include <stack>
#include <algorithm>

using namespace std;
#define Nmax 100007
#define Rezolvare 3

const char iname[] = "ctc.in";
const char oname[] = "ctc.out";


vector<int> rev[Nmax];
vector<int> aux;
vector <int> deg;
queue <int> coada;
vector<int> visited;
vector<int> niv_min;
vector<int> nivel,parent;
stack<int> st;
vector<vector<int> > output;
ifstream f(iname);
ofstream g(oname);

class Graph{
public:
    Graph(int n, int m);
    ~Graph();
    virtual void add_muchie(int x, int y){}
    bool is_correct_graph(vector<int> grade);
private:

protected:
    vector<int> la[Nmax]; //lista de adiacenta;
    int n,m; //numarul de noduri si numarul de muchii
};

bool Graph::is_correct_graph(vector<int> grade)
{
    sort(grade.begin(),grade.end(),greater <int>());
    while(grade[0]!=0)
    {
        int v=grade[0];
        grade.erase(grade.begin()+0);
        if(v>grade.size())
            return false;
        for(int i=0;i<v;i++)
        {
            grade[i]--;
            if(grade[i]<0)
                return false;
        }
        sort(grade.begin(),grade.end(),greater <int>());
    }
    return true;
}

class Undirected: public Graph{
public:
     Undirected(int n, int m=0);
     ~Undirected();
     void add_muchie(int x,int y)
     {
         la[x].push_back(y);
         la[y].push_back(x);
     }
     void dfs(int start,int visited[]);
     void criticalConnections(vector<vector<int>>& connections);
     void biconex();
private:

     void dfs_critical(const int cur);
     void util(const int cur,const int parent);
};
int indx=0;
vector <int> out[Nmax];
void Undirected::util(const int cur,const int parent)
{
        static int time = 0;
        niv_min[cur] = nivel[cur] = ++time;
        st.push(cur);
        for(int j:la[cur])
        {
            if(!niv_min[j])
            {
                util(j,cur);
                niv_min[cur] = min(niv_min[cur],niv_min[j]);
                if(niv_min[j] >= nivel[cur])
                {
                    indx++;
                    while(st.top()!=j){
                        out[indx].push_back(st.top());
                        st.pop();
                    }

                    out[indx].push_back(st.top());
                    st.pop();
                    out[indx].push_back(cur);
                }
             }
            else
                if(j != parent)
                {
                    niv_min[cur]=min(niv_min[cur],nivel[j]);
                }
        }
}

 void Undirected::biconex()
{
    nivel.assign(n+1,-1);
    niv_min.resize(n+1);
    for(int i=0;i<n;i++)
        {
             if(!niv_min[i]){
                util(i,0);
            }
        }
    g<<indx<<endl;
    for(int i=1;i<=indx;i++)
    {
        for(auto j:out[i])
            g<<j<<" ";
        g<<endl;
    }

}
 void Undirected::dfs_critical(int cur)
    {
        static int time=0;
        visited[cur] = 1;
        niv_min[cur] = nivel[cur] = ++time;
        for(int j:la[cur])
        {
            if(!visited[j])
            {
                parent[j] = cur;
                dfs_critical(j);
                niv_min[cur] = min(niv_min[cur],niv_min[j]);
                if(niv_min[j]>nivel[cur])
                {
                    output.push_back({cur,j});
                }
             }
            else
                if(j!=parent[cur])
                    {
                        niv_min[cur]=min(niv_min[cur],nivel[j]);
                    }

        }
    }

void Undirected::criticalConnections(vector<vector<int>>& connections) {
        n=this->n;
        parent.assign(n+1,-1);
        visited.assign(n+1,0);
        niv_min.resize(n+1);
        nivel.resize(n+1);
        for(int i = 0; i < connections.size(); i++)
        {
            la[connections[i][0]].push_back(connections[i][1]);
            la[connections[i][1]].push_back(connections[i][0]);
        }
        for(int i=0;i<n;i++)
        {
             if(visited[i]==0){
                dfs_critical(i);
            }
        }

        for(int i=0;i<output.size();i++)
            cout<<output[i][0]<<" "<<output[i][1]<<endl;
    }

int nr_conex=0;
void Undirected::dfs(int start,int visited[])
{
  visited[start] = nr_conex;
  for(auto i:la[start])
  {
      if(!visited[i])
        dfs(i,visited);
  }
}
 Undirected::Undirected(int n, int m): Graph(n,m)
{

}

Undirected::~Undirected()
{

}

class Directed: public Graph{
public:
     Directed(int n,int m);
     ~Directed();
     void add_muchie(int x,int y);
     void bfs(int start, int visited[],int dist[]);
     void findCTC();
     void reverse();
     void topologic(vector <int>& deg);
private:

    void dfs_plus(int i,stack<int> &my_stack,int visited[]);
    void dfs_reverse(int i,vector <int>& aux,int visited[]);
};


void Directed::topologic(vector <int>& deg)
{
    for(int i=1;i<=n;i++)
        if(!deg[i]) coada.push(i);
    while(!coada.empty())
    {
        for(auto j:la[coada.front()])
        {
            deg[j]--;
            if(!deg[j]) coada.push(j);
        }
        g<<coada.front()<<" ";
        coada.pop();
    }
}



void Directed::dfs_reverse(int i,vector <int>& aux,int visited[])
    {
        visited[i]=1;
        for(auto j:rev[i])
        {
            if(!visited[j])
                dfs_reverse(j,aux,visited);
        }
        aux.push_back(i);
    }
void Directed::findCTC()
     {
         int visited[n];
         vector< vector<int> > sol;
         for(int i=1;i<=n;i++)
            visited[i]=0;
         stack<int> my_stack;
         for(int i=1;i<=n;i++)
            if(!visited[i])
                dfs_plus(i,my_stack,visited);



        for(int i=1;i<=n;i++)
            visited[i]=0;
        int scc = 0;

         while(!my_stack.empty())
         {

             int cur = my_stack.top();
             my_stack.pop();
             if(!visited[cur])
                {
                    aux = vector<int>();
                    dfs_reverse(cur,aux,visited);
                    sol.push_back(aux);
                    scc++;
                }
         }
         g<<scc<<"\n";
         for(int i=0;i<sol.size();i++)
         {
             for(int j=0;j<sol[i].size();j++)
                g<<sol[i][j]<<" ";
          g<<"\n";
         }
     }

void Directed::reverse()
{
    for(int i=1;i<=n;i++)
    {
        for(int j:la[i])
            rev[j].push_back(i);
    }
}

void Directed::dfs_plus(int i,stack<int> &my_stack,int visited[])
{
    visited[i]=1;
    for(int j:la[i])
    {
        if(!visited[j])
            dfs_plus(j,my_stack,visited);
    }
    my_stack.push(i);
}
Directed::Directed(int n, int m): Graph(n,m)
{

}
Directed::~Directed()
{

}
void Directed::add_muchie(int x,int y)
{
    la[x].push_back(y);

}

void Directed::bfs(int start, int visited[],int dist[]){
    queue <int> coada;
    visited[start]=true;
    coada.push(start);
    dist[start] = 0;
    while(!coada.empty())
    {   start = coada.front();
        coada.pop();
        for(auto i:la[start])
        {
            if(!visited[i])
            {
                visited[i] = true;
                coada.push(i);
                dist[i]=dist[start]+1;
            }
        }
    }
}
Graph::Graph(int n=0, int m=0):n(n),m(m)
{

}
Graph::~Graph()
{

}



int main()
{
    int n,m,s;
    int x,y;
    switch(Rezolvare)
    {

    case 1:
    {
     f>>n>>m>>s;
     Directed grf(n,m);
     for(int i=0;i<m;i++)
     {
      f>>x>>y;
      grf.add_muchie(x,y);
     }
     f.close();
     int visited[n],dist[n];
     for(int i=0;i<=n;i++)
        visited[i]=dist[i]=0;
     grf.bfs(s,visited,dist);
     for(int i=1;i<=n;i++)
     {
         if(visited[i])
            g<<dist[i]<<" ";
        else g<<-1<<" ";
     }
        break;
    }
    case 2:
    {
     f>>n>>m;
     Undirected grf(n,m);
     int visited[n];
     for(int i=0;i<m;i++)
      {
      f>>x>>y;
      grf.add_muchie(x,y);
      }
     for(int i=0;i<=n;i++)
        visited[i]=0;
       for(int i=1;i<=n;i++)
        if(!visited[i])
         {
             nr_conex++;
             grf.dfs(i,visited);
         }
    g<<nr_conex;
    break;
    }
    case 3:
    {

     f>>n>>m;
     Directed grf(n,m);
     for(int i=0;i<m;i++)
     {
         f>>x>>y;
         grf.add_muchie(x,y);
     }
     grf.reverse();

     grf.findCTC();
     break;
    }
    case 4:
 {
    vector<int> check;
   int number;
   cin>>number;
   for(int i=0;i<number;i++)
   {
       int c;
       cin>>c;
       check.push_back(c);
   }
   Graph grf(n);
   if(grf.is_correct_graph(check))
     cout<<"DA";
   else cout<<"NU";
   break;
    }
    case 5:
        {
     f>>n>>m;
     Directed grf(n,m);
     deg = vector<int>(n+1,0);
     for(int i=0;i<m;i++)
     {

      f>>x>>y;
      grf.add_muchie(x,y);
      deg[y]++;
     }

     f.close();
     grf.topologic(deg);
     break;
        }

    case 6:
    {
       Undirected grf(4,0);
       vector<vector<int> > connections;
       connections.push_back({0,1});
       connections.push_back({1,2});
       connections.push_back({2,0});
       connections.push_back({1,3});
       grf.criticalConnections(connections);
       break;
    }
    case 7:
    {
        f>>n>>m;
        Undirected grf(n,m);
        for(int i=0;i<m;i++)
        {
            f>>x>>y;
            grf.add_muchie(x,y);
        }
        grf.biconex();
        break;
    }
    }
    g.close();
    return 0;
}