Cod sursa(job #2907189)

Utilizator MoraruLiviuMoraru Mihai-Liviu MoraruLiviu Data 29 mai 2022 11:04:40
Problema Paduri de multimi disjuncte Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.84 kb
#include<bits/stdc++.h>

using namespace std;


//ifstream fin("bfs.in");
//ofstream fout("bfs.out");

//ifstream fin("dfs.in");
//ofstream fout("dfs.out");

//ifstream fin("sortaret.in");
//ofstream fout("sortaret.out");

//ifstream fin("biconex.in");
//ofstream fout("biconex.out");

ifstream fin("disjoint.in");
ofstream fout("disjoint.out");

struct edge{
    int x, y;
    edge(int x1, int y1){
        x=x1;
        y=y1;
    }
    edge(){}
};

class Graph{
private:
    int N, M;
    bool is_directed, has_costs;
    vector<vector<int>> adjacency_list;

public:
    Graph(int N, int M, bool is_directed, bool has_costs);
    void Add_edge(int x, int y);

    void bfs(queue<int> &q, vector<bool> &visited, vector<int> &distance);
    vector<int> bfs_distance(int x);
    void dfs(int x, vector<bool> &visited);
    void bcc(int x, int parent, vector<int> &discovery_time, vector<int> &low, stack<edge> &edge_stack, int &time, vector<set<int>> &bc_components, vector<bool> &visited);
    void Topological_Sort(int x, vector<bool>& visited, vector<int>& sorted);

    int Find(int x, vector<int> &parent);
    void Union(int x, int y, vector<int> &parent, vector<int> &rank);
    void Kruskal(vector<int> &parent, vector<int> &rank, int &cost);

};

    Graph::Graph(int N, int M, bool is_directed, bool has_costs){
        this->N = N;
        this->M = M;
        this->is_directed = is_directed;
        this->has_costs = has_costs;
        adjacency_list.resize(N+1);
    }

    void Graph::Add_edge(int x, int y){
        adjacency_list[x].push_back(y);
        if(!is_directed)
            adjacency_list[y].push_back(x);
    }

    void Graph::bfs(queue<int> &q, vector<bool> &visited, vector<int> &distance){

        while(!q.empty()){
            int current_node = q.front();
            for(int i=0; i<adjacency_list[current_node].size(); i++){
                if(!visited[adjacency_list[current_node][i]]){
                    q.push(adjacency_list[current_node][i]);
                    visited[adjacency_list[current_node][i]] = true;
                    distance[adjacency_list[current_node][i]] = distance[current_node]+1;
                }
            }
            q.pop();
        }

    };

    vector<int> Graph::bfs_distance(int x){
        queue<int> q;
        vector<bool> visited(N+1);
        vector<int> distance(N+1, -1);

        q.push(x);
        visited[x] = true;
        distance[x] = 0;
        bfs(q, visited, distance);
        return distance;
    };


void BFSInfoarena(){
    int N,M,S;
    fin>>N>>M>>S;
    Graph g(N,M,true,false);
    int x, y;
    for(int i=0; i<M; i++){
        fin >> x >> y;
        g.Add_edge(x, y);
    }
    vector<int> rezolvare = g.bfs_distance(S);
    for(int i = 1; i < rezolvare.size(); i++){
        fout<<rezolvare[i]<<" ";
    }
}


    void Graph::dfs(int x, vector<bool> &visited){
        visited[x] = true;
        for(int i = 0; i < adjacency_list[x].size(); i++){
            if (!visited[adjacency_list[x][i]]){
                dfs(adjacency_list[x][i], visited);
            }
        }
    }

void DFSInfoarena(){
    int N,M;
    fin>>N>>M;
    Graph g(N,M,false,false);
    vector<bool> visited(N+1);

    int x,y;
    for(int i = 0; i < M; i++){
        fin>>x>>y;
        g.Add_edge(x, y);
    }

    int counter = 0;
    for(int i = 1; i <= N; i++){
        if(!visited[i]){
            g.dfs(i, visited);
            counter++;
        }
    }

    fout<<counter;
}



    void Graph::Topological_Sort(int x, vector<bool>& visited, vector<int>& sorted){
        visited[x] = true;
        for(int i=0; i<adjacency_list[x].size(); i++){
            if (!visited[adjacency_list[x][i]])
                Topological_Sort(adjacency_list[x][i], visited, sorted);
        }
        sorted.push_back(x);
    }

void SortaretInfoarena(){
    int N,M;
    fin>>N>>M;
    Graph g(N,M,true,false);

    int x,y;
    for(int i = 0; i < M; i++){
        fin>>x>>y;
        g.Add_edge(x, y);
    }

    vector<bool> visited(N+1);
    vector<int> sorted;
    for(int i = 1; i <= N; i++){
        if(!visited[i])
            g.Topological_Sort(i, visited, sorted);
    }
    for(int i =  sorted.size()-1; i > -1; i--){
        fout<<sorted[i]<<" ";
    }
}

    void Graph::bcc(int x, int parent,  vector<int> &discovery_time, vector<int> &low, stack<edge> &edge_stack, int &time, vector<set<int>> &bc_components, vector<bool> &visited){
        visited[x] = true;
        discovery_time[x] = low[x] = time++;

        for(int i = 0; i < adjacency_list[x].size(); i++){
            if(!visited[adjacency_list[x][i]]){
                edge_stack.push(edge(x, adjacency_list[x][i]));
                bcc(adjacency_list[x][i], x, discovery_time, low, edge_stack, time, bc_components, visited);

                if(low[x] > low[adjacency_list[x][i]])
                    low[x] = low[adjacency_list[x][i]];

                if(discovery_time[x] <= low[adjacency_list[x][i]]){
                    set<int> component;
                    int a, b;
                    do {
                        edge e=edge_stack.top();
                        edge_stack.pop();
                        a = e.x;
                        b = e.y;
                        component.insert(a);
                        component.insert(b);
                    }while(a != x || b != adjacency_list[x][i]);
                    bc_components.push_back(component);
                }
            }
            else{
                if(adjacency_list[x][i] != parent){
                    if(low[x] > discovery_time[adjacency_list[x][i]])
                        low[x] = discovery_time[adjacency_list[x][i]];
                }
            }
        }
    }

void BiconexInfoarena(){
    int N,M;
    fin>>N>>M;
    Graph g(N,M,true,false);

    int x,y;
    for(int i = 0; i < M; i++){
        fin>>x>>y;
        g.Add_edge(x, y);
    }

    vector<set<int>> bc_components;
    vector<int> discovery_time(N+1);
    vector<bool> visited(N+1);
    vector<int> low(N+1);
    stack<edge> edge_stack;
    int time = 0;

    for(int i = 1; i <= N; i++){
        if(!visited[i])
            g.bcc(i, 0, discovery_time, low, edge_stack, time, bc_components, visited);
    }

    fout << bc_components.size() << '\n';
    for(int i = 0; i < bc_components.size(); i++){
        for(set<int>::iterator iter = bc_components[i].begin(); iter != bc_components[i].end(); iter++)
            fout << *iter << " ";
        fout << '\n';
    }
}

    int Graph::Find(int x, vector<int> &parent){
        while (x != parent[x])
            x = parent[x];
        return x;
    }

    void Graph::Union(int x, int y, vector<int> &parent, vector<int> &rank){
        int px = Find(x, parent);
        int py = Find(y, parent);

        if(px == py)
            return;

        if(rank[px] <= rank[py]){
            parent[px] = py;
            rank[py] += rank[px];
        }
        else {
            parent[py] = px;
            rank[px] += rank[py];
        }
    }

void DisjointInfoarena(){
    int N,M;
    fin>>N>>M;
    Graph g(N,M,false,false);

    vector<int> parent(N+1);
    vector<int> rank(N+1);

    for(int i = 0; i <= N; i++){
        parent[i] = i;
    }

    for(int i = 0; i < M; i++){
        int cod, x, y;
        fin >> cod >> x >> y;

        if(cod == 1){
            g.Union(x, y, parent, rank);
        }
        else{
            if (g.Find(x, parent) == g.Find(y, parent)){
                fout<< "DA"<<'\n';
            }
            else{
                fout<<"NU"<<'\n';
            }
        }
    }

}


int main()
{
//    BFSInfoarena();
//    DFSInfoarena();
//    SortaretInfoarena();
//    BiconexInfoarena();

    DisjointInfoarena();
    return 0;
}