Cod sursa(job #2822488)

Utilizator bogdan2405Strat Bogdan-Valentin bogdan2405 Data 24 decembrie 2021 00:08:53
Problema Parcurgere DFS - componente conexe Scor 15
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 16.52 kb
#include <bits/stdc++.h>
//#include "Graph.h"
//#include "Tree.h"
using namespace std;

ifstream  f("dfs.in");
ofstream g("dfs.out");

vector<int> freq;

class Tree {
private:
    int m_n,m_m;
public:
    int findParent(int x,vector<int> &parent);

    vector<string> DisjointMain(vector<vector<int>> questions);

    Tree(int mN, int mM);
};

int Tree::findParent(int x,vector<int> &parent) {
    while(parent[x]!=x)
        x=parent[x];

    return x;
}

vector<string> Tree::DisjointMain(vector<vector<int>> questions) {
    vector<string> responses;
    vector<int> parent;
    vector<int> height;

    int i;
    for(i=0;i<m_n;++i){
        parent.push_back(i);
        height.push_back(1);
    }

    for(i=0;i<m_m;++i){
        if(questions[i][0]==1){
            int x=findParent(questions[i][1]-1,parent);
            int y=findParent(questions[i][2]-1,parent);

            if(height[x]>=height[y]){
                parent[y]=x;
                height[x]=height[x]+height[y];
            }
            else{
                parent[x]=y;
                height[y]=height[y]+height[x];
            }
        }
        else if(questions[i][0]==2){
            int x=findParent(questions[i][1]-1,parent);
            int y=findParent(questions[i][2]-1,parent);
            if(x==y)
                responses.push_back("DA\n");
            else
                responses.push_back("NU\n");

        }
    }
    return responses;
}

Tree::Tree(int mN, int mM) : m_n(mN), m_m(mM) {}

class Graph {
private:
    int m_n,m_m;
    bool m_oriented,m_cost;
    vector<int> m_adjList[100001];
    vector<pair<int,int>> m_adjListCost[100000];
    //vector<int> m_visited;
public:
    Graph(int mN, int mM, bool mOriented,bool mCosts);

    void setNrNoduri(int mN);

    void setNrMuchii(int mM);

    void addEdge(int x,int y,int c=0);

    void BFS(int x,int &distanta,vector<int> &dist,queue<int> &q,vector<int> &visited);
    vector<int> distanceFromOneNodeToOthers(int s);

    void DFSbiconex(int x,int parent,vector<int> &visited,vector<int> &low,vector<int> &id,int temp,stack<int> &st,vector<int> &aux,vector<vector<int>> &res);
    vector<vector<int>> BiconexComponents();

    void DFSctc(int x,vector<int> &visited,stack<int> &st);
    void Kosaraju(int x,int node, vector<int> &visited,vector<vector<int>> &adjListTrans,vector<vector<int>> &ctc);
    vector<int> CTC();

    void DFS(int x/*,vector<int> &freq*/);
    int numberOfComponents();

    static bool comp(int a,int b){
        return a>b;
    }
    bool HavelHakimi(vector<int> &grades);
    bool verify(vector<int> &v);
    bool HavelHakimiMain();

    vector<int> SortareTopologica();

    void DFSCriticalConnection(int x,int parrent,vector<int> &low,vector<int> &id,int timp,vector<vector<int>> &result,vector<int> &visited);
    vector<vector<int>> CriticalConnection();

    struct CustomCompare{
        bool operator()(const vector<int> &a, const vector<int> &b){
            return a[2]>b[2];
        }
    };
    void Prim(int x,vector<int> &isInApm, priority_queue<vector<int>,vector<vector<int>>,CustomCompare> &heap,vector<pair<int, int>> &muchii, int cost);
    vector<pair<int,int>> APM();

    struct CustomCompare2{
        bool operator()(const pair<int,int> &a, const pair<int,int> &b){
            return a.second>b.second;
        }
    };
    void Dijkstra(int x,vector<int> &isMarked, priority_queue<pair<int,int>,vector<pair<int,int>>,CustomCompare2> &heap, vector<int> &length);
    vector<int> DijkstraResult();

    void BFSdarb(int x,int varfUltim,queue<int> &q, vector<int> &visited);
    int Darb();

    vector<vector<int>> RoyFloyd(vector<vector<int>> matrix);

    vector<int> Eulerian(int x,vector<int> &euler,vector<int> &visited,stack<int> &st);
    vector<int>  EulerianMain();
};

void Graph::addEdge(int x,int y,int c) {
    if(m_cost==false){
        if(m_oriented==false)
            m_adjList[x].push_back(y);
        else{
            m_adjList[x].push_back(y);
            m_adjList[y].push_back(x);
        }
    }
    else{
        if(m_oriented==false)
            m_adjListCost[x].push_back(make_pair(y,c));
        else{
            m_adjListCost[x].push_back(make_pair(y,c));
            m_adjListCost[y].push_back(make_pair(x,c));
        }
    }

}

void Graph::setNrNoduri(int mN) {
    m_n = mN;
}

void Graph::setNrMuchii(int mM) {
    m_m = mM;
}

void Graph::BFS(int x,int &distanta,vector<int> &dist,queue<int> &q,vector<int> &visited) {
    int i;
    q.push(x);
    if(visited[x-1]==0){
        dist[x-1]=distanta;
        visited[x-1]++;
        distanta++;
    }

    while(!q.empty()){
        int first=q.front();
        q.pop();

        for(i=0;i<m_adjList[first].size();++i){
            if(visited[m_adjList[first][i]-1]==0){
                visited[m_adjList[first][i]-1]++;
                dist[m_adjList[first][i]-1]=dist[first-1]+1;
                q.push(m_adjList[first][i]);
            }
        }


    }
}

vector<int> Graph::distanceFromOneNodeToOthers(int s) {
    vector<int> dist;
    queue<int> q;
    vector<int> visited;
    int distanta=0, i;

    for(int i=0;i<m_n;++i)
        visited.push_back(0);

    BFS(s,distanta,dist,q,visited);

    for(i=0;i<m_n;++i){
        if(visited[i]==0){
            dist[i]=-1;
        }
    }

    return dist;
}

void Graph::DFSbiconex(int x, int parent,vector<int> &visited,vector<int> &low,vector<int> &id,int temp,stack<int> &st,vector<int> &aux,vector<vector<int>> &res) {
    int i;
    id[x]=temp;
    low[x]=temp;
    temp++;
    st.push(x);

    for(i=0;i<m_adjList[x].size();++i){
        if(parent!=m_adjList[x][i]){
            if(visited[m_adjList[x][i]]==0){
                visited[m_adjList[x][i]]++;
                DFSbiconex(m_adjList[x][i],x,visited,low,id,temp,st,aux,res);

                low[x]=min(low[x],low[m_adjList[x][i]]);

                if(id[x]<=low[m_adjList[x][i]]){
                    while(!st.empty() && st.top()!=m_adjList[x][i]){
                        aux.push_back(st.top()+1);
                        st.pop();
                    }
                    aux.push_back(m_adjList[x][i]+1);
                    st.pop();
                    aux.push_back(x+1);
                    res.push_back(aux);
                    aux.clear();
                }

            }
            else{
                low[x]=min(low[x],id[m_adjList[x][i]]);

            }
        }
    }
}

vector<vector<int>> Graph::BiconexComponents() {
    vector<int> visited,low,id;
    int temp=0,cnt=0,i;
    stack<int> st;
    vector<vector<int>> res;
    vector<int> aux;

    for(i=0;i<m_n;++i){
        visited.push_back(0);
        id.push_back(0);
        low.push_back(0);
    }

    for(i=0;i<m_n;++i){
        if(visited[i]==0){
            visited[i]++;
            DFSbiconex(i,-1,visited,low,id,temp,st,aux,res);
            while(!st.empty()){
                st.pop();
            }
        }
    }


    return res;
}

void Graph::DFSctc(int x, vector<int> &visited,stack<int> &st) {
    int i;
    for(i=0;i<m_adjList[x].size();++i){
        if(visited[m_adjList[x][i]-1]==0){
            visited[m_adjList[x][i]-1]++;
            //cout<<adjList[x][i]<<' ';
            DFSctc(m_adjList[x][i],visited,st);
        }
    }
    cout<<x<<' ';
    st.push(x);
}


void Graph::Kosaraju(int x, int node, vector<int> &visited, vector<vector<int>> &adjListTrans, vector<vector<int>> &ctc) {
    int i;
    for(i=0;i<adjListTrans[x].size();++i){
        if(visited[adjListTrans[x][i]-1]==1){
            visited[adjListTrans[x][i]-1]++;
            ctc[node].push_back(adjListTrans[x][i]);
            Kosaraju(adjListTrans[x][i],node,visited,adjListTrans,ctc);
        }
    }
}

vector<int> Graph::CTC() {
    vector<int> adjListTrans[100001], ctc[100001];
    vector<int> visited;
    stack<int> st;
    vector<int> nodes;
    int i;

    for(i=0;i<m_n;++i)
        visited.push_back(0);

    for(i=0;i<visited.size();++i){
        if(visited[i]==0){
            visited[i]++;
            DFSctc(i+1,visited,st);
        }
    }

    int count=0;
    while(!st.empty()){
        int node=st.top();
        if(visited[node-1]==1){
            visited[node-1]++;
            nodes.push_back(node);
            ctc[node].push_back(node);
            count++;
            Kosaraju(node, node, visited, reinterpret_cast<vector<vector<int>> &>(adjListTrans),
                     reinterpret_cast<vector<vector<int>> &>(ctc));
        }

        st.pop();

    }
    return reinterpret_cast<const vector<int> &>(ctc);
}

void Graph::DFS(int x/*,vector<int> &freq*/) {
    int i;

    for(i=0;i<m_adjList[x].size();++i){
        if(freq[m_adjList[x][i]-1]==0){  //verific daca am trecut prin nod
            freq[m_adjList[x][i]-1]++;
            //cout<<adjList[x][i]<<' ';
            DFS(m_adjList[x][i]/*,freq*/);
        }

    }
}

int Graph::numberOfComponents() {
    //vector<int> freq;
    int count=0;

    int i,j;

    for(i=0;i<m_n;++i){
        freq.push_back(0);
    }
    for(i=0;i<freq.size();++i){
        if(freq[i]==0){  ///verific faca am trecut prin nod

            //cout<<'\n';
            freq[i]++;
            count++;   //numar componenta conexa
            DFS(i+1/*,freq*/);
        }

    }

    return count;
}

/*static bool Graph::comp(int a, int b) {
    return a>b;
}*/

bool Graph::HavelHakimi(vector<int> &grades) {
    int i;
    sort(grades.begin(),grades.end(),comp);


    while(grades.size()>0){
        if(grades[0]>=grades.size())
            return false;

        for(i=1;i<=grades[0];++i){
            grades[i]--;
            if(grades[i]<0){
                return false;
            }

        }

        grades.erase(grades.begin());
        sort(grades.begin(),grades.end(),comp);
    }

    return true;
}

bool Graph::verify(vector<int> &v) {
    int sum=0,i;

    for(i=0;i<v.size();++i){
        sum+=v[i];
        if(v[i]>=v.size())
            return false;
    }

    if(sum%2==1)
        return false;

    return true;
}

bool Graph::HavelHakimiMain() {
    vector<int> grades;



    if(verify(grades)==true){
        return HavelHakimi(grades);
    }
    else
        return false;
}

vector<int> Graph::SortareTopologica() {
    stack<int> st;
    vector<int> visited;
    vector<int> sortat;
    int i;
    for(i=0;i<m_n;++i){
        visited.push_back(0);
    }
    for(i=0;i<visited.size();++i){
        if(visited[i]==0){
            visited[i]++;
            DFSctc(i,visited,st);
        }
    }

    while(!st.empty()){
        sortat.push_back(st.top()+1);
        st.pop();
    }

    return sortat;
}



void Graph::Prim(int x,vector<int> &isInApm, priority_queue<vector<int>,vector<vector<int>>,CustomCompare> &heap,vector<pair<int, int>> &muchii, int cost) {
    isInApm[x]++;
    int i;
    for(i=0;i<m_adjListCost[x].size();++i){
        if(isInApm[m_adjListCost[x][i].first]==0){
            vector<int> aux;
            aux.push_back(x);
            aux.push_back(m_adjListCost[x][i].first);
            aux.push_back(m_adjListCost[x][i].second);
            heap.push(aux);
            aux.clear();
        }
    }
    vector<int> first;
    while(heap.size()>0){
        first=heap.top();
        heap.pop();
        if(isInApm[first[0]]==1 && isInApm[first[1]]==0){
            muchii.push_back(make_pair(first[0],first[1]));
            cost=cost+first[2];
            Prim(first[1],isInApm,heap,muchii,cost);
        }

        else if(isInApm[first[0]]==0 && isInApm[first[1]]==1){
            muchii.push_back(make_pair(first[0],first[1]));
            cost=cost+first[2];
            Prim(first[0],isInApm,heap,muchii,cost);
        }


    }
}

vector<pair<int, int>> Graph::APM() {
    vector<int> isInApm;
    priority_queue<vector<int>,vector<vector<int>>,CustomCompare>heap;
    int cost=0;
    vector<pair<int,int>> muchii;
    int i;

    for(i=0;i<m_n;++i)
        isInApm.push_back(0);

    Prim(0,isInApm,heap,muchii,cost);

    return muchii;
}

void Graph::Dijkstra(int x,vector<int> &isMarked, priority_queue<pair<int,int>,vector<pair<int,int>>,CustomCompare2> &heap, vector<int> &length) {
    int i;
    isMarked[x]++;
    for(i=0;i<m_adjListCost[x].size();++i){
        if(isMarked[m_adjListCost[x][i].first]==0){
            pair<int,int> aux;
            heap.push(make_pair(m_adjListCost[x][i].first,m_adjListCost[x][i].second+length[x]));
        }

    }

    pair<int,int> frt;
    while(heap.size()>0){
        frt=heap.top();
        heap.pop();
        if(isMarked[frt.first]==0){
            length[frt.first]=frt.second;
            Dijkstra(frt.first,isMarked,heap,length);
        }
    }
}

vector<int> Graph::DijkstraResult() {
    vector<int> isMarked,length;
    priority_queue<pair<int,int>,vector<pair<int,int>>,CustomCompare2>heap;
    int i;

    for(i=0;i<m_n;++i){
        isMarked.push_back(0);
        length.push_back(0);
    }

    Dijkstra(0,isMarked,heap,length);

    return length;
}

void Graph::BFSdarb(int x,int varfUltim,queue<int> &q, vector<int> &visited) {
    int i;
    varfUltim=x;
    q.push(x);

    while(!q.empty()){
        int first=q.front();
        varfUltim=first;
        q.pop();

        for(i=0;i<m_adjList[first].size();++i){
            if(visited[m_adjList[first][i]]==0){
                visited[m_adjList[first][i]]++;

                q.push(m_adjList[first][i]);

            }
        }


    }
}

int Graph::Darb() {
    vector<int> visited,dist;
    queue<int> q;
    int varfUltim,diametru=0;
    int i;
    int distanta=0;

    for(i=0;i<m_n-1;++i) {
        visited.push_back(0);
    }

    visited.push_back(0);

    BFSdarb(0,varfUltim,q,visited);
    diametru=0;
    visited.clear();
    visited.assign(m_n,0);
    dist.assign(m_n,0);
    int varf1=varfUltim;
    BFS(varf1,distanta,dist,q,visited);
    int varf2=varfUltim;
    diametru=dist[varf2]+1;

    return diametru;
}

vector<vector<int>> Graph::RoyFloyd(vector<vector<int>> matrix) {
    //vector<vector<int>> matrix;
    int i,j,k;

    for(i=0;i<m_n;++i)
        for(j=0;j<m_n;++j){
            if(matrix[i][j]==0 && i!=j)
                matrix[i][j]=2000;
        }
    for(k=0;k<m_n;++k){
        for(i=0;i<m_n;++i){
            for(j=0;j<m_n;++j){
                if(matrix[i][j]>matrix[i][k]+matrix[k][j]){
                    matrix[i][j]=matrix[i][k]+matrix[k][j];
                }
            }
        }
    }

    return matrix;
}

vector<int> Graph::Eulerian(int x,vector<int> &euler,vector<int> &visited,stack<int> &st) {
    int i;
    for(i=0;i<m_n;++i){
        if(m_adjListCost[i].size()%2==1){
            return {-1};
        }
    }


    st.push(0);

    while(!st.empty()){

        int node=st.top();


        if(m_adjListCost[node].size()!=0){

            int next=m_adjListCost[node].back().first;
            int j=m_adjListCost[node].back().second;
            m_adjListCost[node].pop_back();

            if(visited[j]==0){
                visited[j]=1;
                st.push(next);
            }

        }
        else
        {
            euler.push_back(node);
            st.pop();
        }
    }
    return euler;
}

vector<int> Graph::EulerianMain() {
    stack<int> st;
    vector<int> euler;
    vector<int> visited; //pentru muchii

    int i;
    visited.assign(m_m+1,0);


    vector<int> eulerRez=Eulerian(0,euler,visited,st);
    if(eulerRez[0]==-1)
        return {-1};
    return eulerRez;
}

Graph::Graph(int mN, int mM, bool mOrientat,bool mCosts) : m_n(mN), m_m(mM), m_oriented(mOrientat),m_cost(mCosts) {}

void Graph::DFSCriticalConnection(int x,int parrent,vector<int> &low,vector<int> &id,int timp,vector<vector<int>> &result,vector<int> &visited) {
    id[x]=timp;
    low[x]=timp;
    timp++;

    int i;
    for(i=0;i<m_adjList[x].size();++i){
        if(parrent!=m_adjList[x][i]){
            if(visited[m_adjList[x][i]]==0){
                visited[m_adjList[x][i]]++;
                DFSCriticalConnection(m_adjList[x][i],x,low,id,timp,result,visited);
                low[x]=min(low[x],low[m_adjList[x][i]]);
                if(id[x]<low[m_adjList[x][i]])
                    result.push_back({x,m_adjList[x][i]});
            }
            else{
                low[x]=min(low[x],id[m_adjList[x][i]]);
                //cout<<x<<adjList[x][i]<<"     ";
            }
        }

    }
}

vector<vector<int>> Graph::CriticalConnection() {
    int timp=0;
    vector<vector<int>> result;
    int parrent;
    vector<int> visited,id,low;

    int i;
    for(i=0;i<m_n;++i){
        visited.push_back(0);
        low.push_back(-1);
        id.push_back(-1);
    }

    visited[0]++;
    DFSCriticalConnection(0,-1,low,id,timp,result,visited);


    return result;
}
int main() {
    int n,m;
    int a,b,c;
    bool oriented,cost;
    f>>n>>m;

    Graph gf(n,m,0,0);

    int i;
    for(i=0;i<m;++i){
        f>>a>>b;
        gf.addEdge(a,b);
    }

    g<<gf.numberOfComponents();
    return 0;
}