Cod sursa(job #2822397)

Utilizator alina225Avram Miruna alina225 Data 23 decembrie 2021 22:25:49
Problema Parcurgere DFS - componente conexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 14.36 kb
#include<bits/stdc++.h>
using namespace std;

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

//pentru APM
struct compare{
    bool operator()(const vector<int> &a, const vector<int> &b){
        return a[2]>b[2]; //compar dupa cost
    }
};

//pentru Dijsktra
struct compare2{
    bool operator()(const pair<int,int> &a, const pair<int,int> &b){
        return a.second>b.second; //compar dupa cost
    }
};

class Graf {

private:

    int m_nodes,m_edges,m_cost;
public:
    void setMCost(int mCost);

private:
    bool m_isDirected;
    bool m_haveCost;
    vector<int> adjList[100001];
    vector<int> rev_adjList[101],component[100001];
    vector<pair<int,int>> adjList_withCost[10001];

public:
    Graf(int mNodes, int mEdges, bool mIsDirected, bool mHaveCost);
    void add_Edge(int from, int to);

    //problema BFS infoarena
    // al i-lea numar reprezinta numarul minim de arce ce trebuie parcurse de la nodul S la nodul i.
    void bfs(int node,vector<int> visited, vector<int>& cost,int &last);
    //-----------------------------
    //problema DFS-----------------
    void dfs(int node,vector<int>& visited,int nrcomp);
    int nr_comp_conexe(vector<int>& visited);
    //-------------------------------
    //problema CTC
    void first_DFS_CTC(int node,vector<int>& visited,stack<int>& st);
    void reverse_CTC();
    void second_DFS_CTC(int node,vector<int>& visited,int nr);
    void nr_SCCs(int &nr,vector<int>& visited);

    const vector<int> *getComponent() const;

    //Havel Hakimi
    int verify(vector<int> grades);
    string answer(vector<int> grades);
    //APM
    void apm(int node,vector<int>& visited,priority_queue<vector<int>,vector<vector<int>>,compare>& heap,vector<pair<int,int>>& muchii,int& cost_total);
    void Dijkstra(int node,vector<int>& visited, vector<int>& dist,priority_queue<pair<int,int>,vector<pair<int,int>>,compare2>& heap);
    void topo(unordered_map<int,int>& intern_grade,vector<int>& topo_sort,queue<int>& q);
    //vector<vector<int>> RoyFloyd(int cost[101][101]);
    void euler_cycle(int start,vector<int> &ans,unordered_map<int,int> to,unordered_map<int,int> from,unordered_map<int,int> d);
};
const vector<int> *Graf::getComponent() const {
    return component;
}


//constructorul
Graf::Graf(int mNodes, int mEdges, bool mIsDirected, bool mHaveCost) : m_nodes(mNodes), m_edges(mEdges),
                                                                       m_isDirected(mIsDirected),
                                                                       m_haveCost(mHaveCost) {
}
void Graf::setMCost(int mCost) {
    m_cost = mCost;
}

//adaugare muchii pentru orientat si neorientat
void Graf::add_Edge(int from, int to) {
    if(m_haveCost==0) {

        if (m_isDirected == 0) //este neorientat
        {
            adjList[from].push_back(to);
            adjList[to].push_back(from);
        } else //este orientat
            adjList[from].push_back(to);
    }
    else{

        if (m_isDirected == 0) //este neorientat
        {
            adjList_withCost[from].push_back(make_pair(to,m_cost));
            adjList_withCost[to].push_back(make_pair(from,m_cost));

        } else //este orientat
            adjList_withCost[from].push_back(make_pair(to,m_cost));

    }
    }








void Graf::bfs(int node, vector<int> visited, vector<int>& cost, int &last) {
    int a;
    queue<int> q;
    visited.assign(m_nodes+1,0);
    cost.assign(m_nodes+1,-1);
    visited[node]=1;
    cost[node]=0;
    q.push(node);
    while(!q.empty()){
        node=q.front();
        last=node;
        a=cost[node];
        q.pop();
        for(auto i:adjList[node])
        {
            if(visited[i]==0){
                visited[i]=1;
                cost[i]=a+1;
                q.push(i);
            }
        }
    }

}

void Graf::dfs(int node, vector<int> &visited,int nrcomp) {
    int i;
    visited[node]=nrcomp;
    for(i=0;i<adjList[node].size();i++){
        if(!visited[adjList[node][i]]){
            dfs(adjList[node][i],visited,nrcomp);
        }
    }
}

int Graf::nr_comp_conexe(vector<int>& visited) {

    int nrcomp=0;
    for(int i=0;i<=m_nodes;i++)
    {
        visited.push_back(0);
    }

    for(int i=1;i<=m_nodes;i++)
    {
        if(visited[i]==0){
            nrcomp++;
            dfs(i,visited,nrcomp);
        }
    }
    return nrcomp;
}


void Graf::first_DFS_CTC(int node, vector<int> &visited, stack<int> &st) {
    visited[node]=1;
    for(auto i:adjList[node])
        if(visited[i]==0)
            first_DFS_CTC(i,visited,st);
    st.push(node);

}

void Graf::reverse_CTC() {

    for(int i=0;i<m_nodes;i++){
        for(auto j:adjList[i])
            rev_adjList[j].push_back(i);
    }

}

void Graf::second_DFS_CTC(int node, vector<int> &visited,  int nr) {
    component[nr].push_back(node+1);
    visited[node]=1;
    for(auto i:rev_adjList[node])
        if(visited[i]==0)
        {
            second_DFS_CTC(i,visited,nr);
        }
}


void Graf::nr_SCCs(int &nr,vector<int>& visited){
    nr=0;
    stack<int> st;
    for(int i=0;i<m_nodes;i++){
        for(auto j:adjList[i])
            component[j].push_back(i);
    }

    for(int i=0;i<m_nodes;i++){
        visited.push_back(0);
    }

    for(int i=0;i<m_nodes;i++){
        if(visited[i]==0)
            first_DFS_CTC(i,visited,st);
    }

    reverse_CTC();

    for(int i=0;i<m_nodes;i++){
        visited[i]=0;
    }

    while(!st.empty()){

        int a=st.top();
        st.pop();
        if(visited[a]==0){
            nr++;
            second_DFS_CTC(a,visited,nr);
        }
    }

}

//Havel Hakimi
int Graf::verify(vector<int> grades){
    int sum=0;
    for(int i=0;i<grades.size();i++){
        if(grades[i]>grades.size()-1)
            return 0;
        sum+=grades[i];
    }
    if(sum %2 == 1 )
        return 0;
    return 1;
}

string Graf::answer(vector<int> grades){
    if(verify(grades)){
        while(grades.size() != 0 ){
            sort(grades.begin(),grades.end(), greater<int>());
            int a=grades[0];
            grades.erase(grades.begin());
            for(int i=0;i<a;i++){
                if(grades[i]-1<0)
                    return "NU";
                else
                    grades[i]-=1;
            }
        }
        return "DA";
    }
    return "NU";
}



//APM
void Graf::apm(int node,vector<int>& visited,priority_queue<vector<int>,vector<vector<int>>,compare>& heap,vector<pair<int,int>>& muchii,int& cost_total){
    visited[node]=1;

    for(int i=0;i<adjList_withCost[node].size();i++){
        if(visited[adjList_withCost[node][i].first]==0) //parcurg lista de adiacenta si vad daca a fost vizitat fiecare nod
//bag in heap (u,v,cost(u,v))
        {
            vector<int> aux;
            aux.push_back(node);
            aux.push_back(adjList_withCost[node][i].first);
            aux.push_back(adjList_withCost[node][i].second);
            heap.push(aux);

        }
    }
    while(heap.size()!=0){
        vector<int> top;
        top=heap.top();
        heap.pop();

        if(visited[top[0]]==1 && visited[top[1]]==0) //u e in apm, dar v nu
        {
            cost_total+=top[2];
            muchii.push_back(make_pair(top[0],top[1])); //pun in muchii (u,v)
            apm(top[1],visited,heap,muchii,cost_total);
        }

    }

}

//Dijkstra

void Graf::Dijkstra(int node,vector<int>& visited, vector<int>& dist,priority_queue<pair<int,int>,vector<pair<int,int>>,compare2>& heap){
    visited[node]=1;

    for(int i=0;i<adjList_withCost[node].size();i++){
        if(visited[adjList_withCost[node][i].first]==0) //parcurg lista de adiacenta si vad daca a fost vizitat fiecare nod
//bag in heap (u,v,cost(u,v))
        {

            heap.push(make_pair(adjList_withCost[node][i].first,adjList_withCost[node][i].second+dist[node]));

        }
    }
    while(heap.size()!=0){
        pair<int,int> top;
        top=heap.top();
        heap.pop();

        if(visited[top.first]== 0) //u e in apm, dar v nu
        {
            dist[top.first]=top.second;
            Dijkstra(top.first,visited,dist,heap);
        }

    }

}

void Graf::topo(unordered_map<int,int>& intern_grade,vector<int>& topo_sort,queue<int>& q){
    for(int i=1;i<=m_nodes;i++)
        if(intern_grade[i]==0)
            q.push(i);
    while(q.size()!=0){
        int node=q.front();
        q.pop();
        topo_sort.push_back(node);
        for(int i=0;i<adjList[node].size();i++)
        {
            intern_grade[adjList[node][i]]=intern_grade[adjList[node][i]]-1;
            if(intern_grade[adjList[node][i]]==0)
                q.push(adjList[node][i]);
        }
    }
}


void Graf::euler_cycle(int start,vector<int> &ans,unordered_map<int,int> to,unordered_map<int,int> from,unordered_map<int,int> d){
    stack<int> st;
    unordered_map<int,int> visited;
    int ok=0;
    int urmatorul_nod;
    for(int i=1;i<=m_nodes;i++)
    {
        if(d[i]%2 == 1)
        {
            ans.push_back(-1);
            ok=1;
            break;
        }
    }
    if(ok==0) {
        st.push(start);
        while (!st.empty()) {
            int node = st.top();
            if (!adjList[node].empty()) {
                int numar_muchie = adjList[node].back();
                adjList[node].pop_back();
                if (visited[numar_muchie] == 0) {
                    visited[numar_muchie] = 1;
                    if (to[numar_muchie] != node)
                        urmatorul_nod = to[numar_muchie];
                    else
                        urmatorul_nod = from[numar_muchie];
                    st.push(urmatorul_nod);
                }
            } else {
                ans.push_back(st.top());
                st.pop();
            }
        }
    }

}


void solve_bfs(){
    int n,m,S,x,y;
    f>>n>>m>>S;
    Graf graf(n,m,1,false);

    for(int i=0;i<m;++i)
    {
        f>>x>>y;
        graf.add_Edge(x,y);
    }
    vector<int> cost,visited;
    int last;
    graf.bfs(S,visited,cost,last);
    for(int i=1;i<=n;i++)
        g<<cost[i]<<" ";
}


void solve_dfs_nrCompConexe(){
    int i,n,m,x,y,nrcomp=0;
    f>>n>>m;
    Graf graf(n,m,0,false);
    vector<int> visited;

    for(int i=0;i<m;++i)
    {
        f>>x>>y;
        graf.add_Edge(x,y);
    }
    g<<graf.nr_comp_conexe(visited);

}

//-------------------------CTC--------------------



void solve_CTC()
{

    int n,m,x,y;
    f>>n>>m;
    Graf graf(n,m,1,false);

    for(int i=0;i<m;++i)
    {
        f>>x>>y;
        graf.add_Edge(x-1,y-1);
    }

    vector<int> visited;
    int nr=0;
    graf.nr_SCCs(nr,visited);
    g<<nr<<'\n';
    for(int i=1;i<=nr;i++)
    {
        for(auto j:graf.getComponent()[i])
            if(j!=0)
                g<<j<<" ";
        g<<'\n';
    }
}

//-------------------------Havel Hakimi-------------------------

void solve_Havel_Hakimi(){
    int n,x;
    vector<int> grades;
    f>>n;
    Graf graf(n,0,0,0);
    for(int i=0;i<n;i++)
    {
        f>>x;
        grades.push_back(x);
    }
    g<<graf.answer(grades);

}
//------------------APM--------------
void solve_APM(){

    int n,m,x,y,cost;
    f>>n>>m;
    Graf graf(n,m,0,1);

    for(int i=0;i<m;++i)
    {
        f>>x>>y;
        f>>cost;
        graf.setMCost(cost);
        graf.add_Edge(x,y);
    }
    //vector<int>& visited,priority_queue<vector<int>,vector<vector<int>>,compare>& heap,vector<pair<int,int>>& muchii,int& cost_total
    int cost_total=0;
    vector<pair<int,int>> muchii;
    priority_queue<vector<int>,vector<vector<int>>,compare> heap;
    vector<int> visited;

    for(int i=0;i<=n;i++)
        visited.push_back(0);
    graf.apm(1,visited,heap,muchii,cost_total);
    g<<cost_total<<'\n';
    g<<muchii.size()<<'\n';
    for(auto i:muchii)
        //for(int j=0;j<i.size();j++)
        g<<i.first<<" "<<i.second<<'\n';
}

//-------------------------Dijkstra-----------------

void solve_Dijkstra(){
    int n,m,x,y,cost;
    f>>n>>m;
    Graf graf(n,m,1,1);

    for(int i=0;i<m;++i)
    {
        f>>x>>y;
        f>>cost;
        graf.setMCost(cost);
        graf.add_Edge(x,y);
    }
    vector<int> dist;
    vector<int> visited;
    priority_queue<pair<int,int>,vector<pair<int,int>>,compare2> heap;
    for(int i=0;i<=n;i++)
    {
        visited.push_back(0);
        dist.push_back(0);
    }
    graf.Dijkstra(1,visited,dist,heap);
    for(int i=2;i<=n;i++){
        g<<dist[i]<<" ";
    }
}

//------------------Sortaret----------------------

void solve_Sortaret(){
    int n,m,x,y;
    vector<int> visited;
    queue<int> q;
    unordered_map<int,int> intern_grade;
    vector<int> topo_sort;
    f>>n>>m;
    Graf graf(n,m,1,false);
    for(int i=0;i<m;++i)
    {
        f>>x>>y;
        intern_grade[y]+=1;
        graf.add_Edge(x,y);
    }
    for(int i=0;i<=n;i++)
        visited.push_back(0);

    graf.topo(intern_grade,topo_sort,q);
    for(int i=0;i<topo_sort.size();i++)
        g<<topo_sort[i]<<" ";
}



void solve_DARB(){
    int n,first_node,final,x,y;
    f>>n;
    Graf graf(n,n,0,false);

    for(int i=0;i<n-1;++i)
    {
        f>>x>>y;
        graf.add_Edge(x,y);
    }
    vector<int> cost,visited;
    int last;
    graf.bfs(1,visited,cost,first_node);
    graf.bfs(first_node,visited,cost,final);
    g<<cost[final]+1;

}
void solve_RoyFloyd(){
    int n,x;

    int cost[101][101],d[101][101];

    f>>n;
    for(int i=1;i<=n;i++)
        for (int j=1; j<=n;j++) {
            f >> cost[i][j];
        }

    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if (i!=j && cost[i][j] == 0) {
                d[i][j] = 1001;
            }
            else {
                d[i][j] = cost[i][j];
            }
        }
    for (int k=1;k<=n;k++)
        for (int i=1; i<=n;i++)
            for (int j=1; j<=n; j++)
                if (d[i][j]>d[i][k]+d[k][j]) {
                    d[i][j]=d[i][k]+d[k][j];
                }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            g<<d[i][j]<<" ";
        g<<endl;
    }
}

void solve_eulerCycle(){
    int i,x,y,n,m;
    unordered_map<int,int> from,to,d;
    f>>n>>m;
    Graf graf(n,m,1,false);

    for(int i=0;i<m;++i)
    {
        f>>x>>y;
        d[x]++;
        d[y]++;
        from[i]=x;
        to[i]=y;
        graf.add_Edge(x,i);
        graf.add_Edge(y,i);
    }
    vector<int> ans;
    graf.euler_cycle(1,ans,to,from,d);
    if(ans.size()==1)
        g<<ans[0];
    else
        for(i=0;i<ans.size()-1;i++)
            g<<ans[i]<<" ";
}


int main() {

    //solve_bfs();
    solve_dfs_nrCompConexe();
    //solve_CTC();
    //solve_Havel_Hakimi();
    //solve_APM();
    //solve_Dijkstra();
    //solve_Sortaret();
    //solve_DARB();
    //solve_RoyFloyd();
    //solve_eulerCycle();
    return 0;
}