Cod sursa(job #2818737)

Utilizator MihaiLazar26Lazar Mihai MihaiLazar26 Data 16 decembrie 2021 19:32:33
Problema Componente biconexe Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 21.43 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <climits>

using namespace std;

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

#define NMAX 100001

class Graf{
    vector<int> nod[NMAX];
    vector<pair<int, int>> nodCosturi[NMAX];
    vector<int> viz;
    vector<int> nma;
    vector<int> low;
    vector<bool> inStruct;
    queue<int> coada;
    stack<int> stiva;
    vector<vector<int>> componente;
    int nrNoduri, nrMuchi;
    bool orientat = false, neorientat = false;
    int id;


    typedef pair<int, pair<int, int>> costMuchi;

    void setOrientat(bool orientat = true){
        if(orientat) this->orientat = true, this->neorientat = false;
        else this->orientat = false, this->neorientat = true;
    }

    void setNeorientat(bool neorientat = true){
        if(neorientat) this->neorientat = true, this->orientat = false;
        else this->neorientat = false, this->orientat = true;
    }

    void setViz(int nod, int val){
        this->viz.assign(nod + 1, val);
    }

    void actBFS(int S, vector<int> &viz);
    void actDFS(int S, vector<bool> &viz);
    void biconexeDFS(int S, int Tata, vector<int> &viz, vector<int> &nma, stack<int> &stiva,
                       vector<vector<int>> &componente);

    void ctcDFS(int S);

    void dfsSt(int S);

    void dfsMC(int S, int Tata);

    void actApmPrim(int S, vector<int> &viz, priority_queue<costMuchi, vector<costMuchi>, greater<costMuchi>> &pqMuchi,
                    vector<costMuchi> &results);

    void actDijkstra(int S, vector<int> &dist, vector<bool> &viz,
                     priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> &pqMuchi);

    int bfsMaxflow(int s, int d, vector<int>& parent, vector<vector<int>>& capacitate, vector<vector<int>>& flux,
                   vector<bool>& viz);

public:

    void goleste(){
        viz.clear();
        nma.clear();
        low.clear();
        inStruct.clear();
        while(!stiva.empty()) stiva.pop();
        while(!coada.empty()) coada.pop();
        for(auto vec : componente) vec.clear();
        componente.clear();
    }

    void citire(int nrNoduri, int nrMuchi, vector<pair<int, int>> muchi, bool orientat = true){
        if(orientat) setOrientat();
        else setNeorientat();
        this->nrNoduri = nrNoduri;
        this->nrMuchi = nrMuchi;
        for(auto i : muchi){
            this->nod[i.first].push_back(i.second);
            if(this->neorientat) this->nod[i.second].push_back(i.first);

        }
    }

    void citireCosturi(int nrNoduri, int nrMuchi, vector<pair<int, pair<int, int>>> muchi, bool orientat = true){
        if(orientat) setOrientat();
        else setNeorientat();
        this->nrNoduri = nrNoduri;
        this->nrMuchi = nrMuchi;
        for(auto i : muchi){
            int nodMe = i.second.first;
            int nodT = i.second.second;
            int cost = i.first;

            this->nodCosturi[nodMe].push_back(make_pair(nodT, cost));
            if(this->neorientat) this->nodCosturi[nodT].push_back(make_pair(nodMe, cost));
        }
    }

    void setNrNoduri(int n){
        this->nrNoduri = n;
    }

    void setNrMuchi(int n){
        this->nrMuchi = n;
    }

    void addMuchie(int x, int y){
        nod[x].push_back(y);
    }


    vector<int> BFS(int S);

    int DFS();

    vector<vector<int>> compBiconexe();

    vector<vector<int>> CTC();

    vector<int> ST();

    bool HavelHakimi(vector<int> grade);

    vector<vector<int>> muchiCritice();

    vector<pair<int, pair<int, int>>> apmPrim();

    int findParinte(int x, vector<int> &paduri);

    void disjoint1(int x, int y, vector<int> &paduri);

    bool disjoint2(int x, int y, vector<int> &paduri);

    vector<int> dijkstra();

    pair<vector<int>, bool> bellmanFord(int start);

    int maxflow(int s, int t, vector<vector<int>> &capacitate);

    vector<vector<int>> royfloyd(int n, vector<vector<int>> matAd);

    int darb();
};
Graf graf;


void Graf::actBFS(int S, vector<int> &viz){

    queue<int> coada;

    coada.push(S);
    viz[S] = 0;
    while(!coada.empty()){
        int current = coada.front();
        coada.pop();
        int dist = viz[current] + 1;
        for(auto vecin : nod[current]){
            if(viz[vecin] == -1){
                viz[vecin] = dist;
                coada.push(vecin);
            }
        }
    }
}

vector<int> Graf::BFS(int S){
    vector<int> viz(nrNoduri+1, -1);

    actBFS(S, viz);
    return viz;
}

void Graf::actDFS(int S, vector<bool> &viz){
    viz[S] = 1;
    for(auto vecini : nod[S]){
        if(!viz[vecini]) actDFS(vecini, viz);
    }
}

int Graf::DFS(){
    int componente = 0;

    vector<bool> viz(nrNoduri+1, 0);
    for(int i = 1; i <= nrNoduri; i++){
        if(!viz[i]) actDFS(i, viz), ++componente;
    }
    return componente;
}

void Graf::biconexeDFS(int S, int Tata, vector<int> &viz, vector<int> &nma, stack<int> &stiva,
                       vector<vector<int>> &componente){
    nma[S] = viz[S] = viz[Tata] + 1;
    stiva.push(S);
    for(auto vecin : nod[S]){
        if(vecin != Tata){
            if(viz[vecin]){
                nma[S] = min(nma[S], viz[vecin]);
            }
            else{
                biconexeDFS(vecin, S, viz, nma, stiva, componente);
                nma[S] = min(nma[S], nma[vecin]);

                if(viz[S] <= nma[vecin]){
                    vector<int> comp;
                    while(stiva.top() != vecin){
                        comp.push_back(stiva.top());
                        stiva.pop();
                    }
                    comp.push_back(vecin);
                    stiva.pop();
                    comp.push_back(S);
                    componente.push_back(comp);
                }
            }
        }
    }

}

vector<vector<int>> Graf::compBiconexe(){

    vector<int> viz(nrNoduri+1, 0);
    vector<int> nma(nrNoduri+1, 0);
    stack<int> stiva;
    vector<vector<int>> componente;
    biconexeDFS(1, 0, viz, nma, stiva, componente);
    return componente;
}

void Graf::ctcDFS(int S){
    stiva.push(S);
    inStruct[S] = true;
    viz[S] = low[S] = id++;

    for(auto vecin : nod[S]){
        if(viz[vecin] == -1) ctcDFS(vecin);
        if(inStruct[vecin]) low[S] = min(low[S], low[vecin]);
    }

    if(viz[S] == low[S]){
        vector<int> componenta;
        int node = stiva.top();
        while(node != S){
            inStruct[node] = false;
            componenta.push_back(node);
            stiva.pop();
            node = stiva.top();
        }
        componenta.push_back(node);
        inStruct[node] = false;
        stiva.pop();
        componente.push_back(componenta);
    }
}

vector<vector<int>> Graf::CTC(){
    viz.assign(nrNoduri + 1, -1);
    low.assign(nrNoduri + 1, 0);
    inStruct.assign(nrNoduri + 1, false);
    id = 1;
    for(int i = 1; i <= nrNoduri; i++){
        if(viz[i] == -1) ctcDFS(i);
    }
    return componente;
}

void Graf::dfsSt(int S){
    viz[S] = 1;
    for(auto vecini : nod[S]){
        if(!viz[vecini]) dfsSt(vecini);
    }
    nma.push_back(S);
}

vector<int> Graf::ST(){
    viz.assign(nrNoduri + 1, 0);
    for(int i = 1; i <= nrNoduri; i++){
        if(!viz[i]) dfsSt(i);
    }
    reverse(nma.begin(), nma.end());
    return nma;
}

bool Graf::HavelHakimi(vector<int> grade){
    sort(grade.begin(), grade.end(), greater<int>());


    while(grade.size() && grade[0]){
        int prim = grade[0];
        grade.erase(grade.begin());

        if(prim > grade.size()) return false;

        for(auto& gr : grade){
            if(gr - 1 < 0)
                return false;
            else{
                --gr;
                --prim;
            }
            if(prim == 0) break;
        }
        if(prim) return false;

        sort(grade.begin(), grade.end(), greater<int>());

    }

    if(grade.size() && grade[0] == 0) return true;
    if(grade.size() == 0) return true;

    return false;
}

void Graf::dfsMC(int S, int Tata){
    nma[S] = viz[S] = viz[Tata] + 1;
    for(auto vecin : nod[S]){
        if(vecin != Tata){
            if(viz[vecin]){
                nma[S] = min(nma[S], viz[vecin]);
            }
            else{
                dfsMC(vecin, S);
                nma[S] = min(nma[S], nma[vecin]);

                if(viz[S] < nma[vecin])
                {
                    vector<int> temp;
                    temp.push_back(S);
                    temp.push_back(vecin);
                    componente.push_back(temp);
                }
            }
        }
    }
}

vector<vector<int>> Graf::muchiCritice(){
    viz.assign(nrNoduri+1, 0);
    nma.assign(nrNoduri+1, 0);
    dfsMC(1,0);
    return componente;
}


void Graf::actApmPrim(int S, vector<int> &viz, priority_queue<costMuchi, vector<costMuchi>, greater<costMuchi>> &pqMuchi,
                      vector<costMuchi> &results){

    viz[S] = 1;
    for(auto vecini : nodCosturi[S]){
        int nod = vecini.first;
        int cost = vecini.second;
        if(!viz[nod])
            pqMuchi.push(make_pair(cost, make_pair(S, nod)));
    }

    while(!pqMuchi.empty()){
        auto top = pqMuchi.top();
        pqMuchi.pop();

        int target = top.second.second;

        if(!viz[target]){
            results.push_back(top);
            actApmPrim(target, viz, pqMuchi, results);
        }

    }

}


vector<pair<int, pair<int, int>>> Graf::apmPrim(){
    priority_queue<costMuchi, vector<costMuchi>, greater<costMuchi>> pqMuchi;
    vector<int> viz;
    viz.assign(nrNoduri+1, 0);
    vector<costMuchi> results;
    actApmPrim(1, viz, pqMuchi, results);



    return results;

}


int Graf::findParinte(int x, vector<int> &paduri){
    if(paduri[x] == x) return x;

    paduri[x] = findParinte(paduri[x], paduri);

    return paduri[x];

}

void Graf::disjoint1(int x, int y, vector<int> &paduri){
    int parx = findParinte(x, paduri);
    int pary = findParinte(y, paduri);

    if(parx != pary)
        paduri[pary] = parx;
}

bool Graf::disjoint2(int x, int y, vector<int> &paduri){

    int parx = findParinte(x, paduri);
    int pary = findParinte(y, paduri);

    return (parx == pary);
}

void Graf::actDijkstra(int S, vector<int> &dist, vector<bool> &viz,
                     priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> &pqMuchi){

    dist[S] = 0;
    pqMuchi.push(make_pair(0, S));

    while(!pqMuchi.empty()){
        auto top = pqMuchi.top();
        pqMuchi.pop();

        int target = top.second;
        if(!viz[target]){
            viz[target] = true;

            for(auto vecini : nodCosturi[target]){
                int nod = vecini.first;
                int cost = vecini.second;

                if(dist[target] + cost < dist[nod]){
                    dist[nod] = dist[target] + cost;
                    pqMuchi.push(make_pair(dist[nod], nod));
                }
            }
        }


    }

}


vector<int> Graf::dijkstra(){

    vector<int> dist;
    dist.assign(nrNoduri+1, INT_MAX);

    vector<bool> viz;
    viz.assign(nrNoduri+1, false);

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pqMuchi;

    actDijkstra(1, dist, viz, pqMuchi);

    for(int i = 2; i<=nrNoduri; i++)
        if(dist[i] == INT_MAX) dist[i] = 0;

    return dist;
}

pair<vector<int>, bool> Graf::bellmanFord(int start){

    vector<int> dist;
    dist.assign(nrNoduri + 1, INT_MAX);

    vector<bool> inCoada;
    inCoada.assign(nrNoduri+1, false);

    vector<int> cnt;
    cnt.assign(nrNoduri+1, 0);

    dist[start] = 0;

    queue<int> coada;

    coada.push(start);
    inCoada[start] = true;

    while(!coada.empty()){
        int nod = coada.front();
        coada.pop();
        inCoada[nod] = false;
        cnt[nod]++;
        if(cnt[nod] >= nrNoduri){
            return make_pair(dist, true);
        }

        for(auto vecini : nodCosturi[nod]){
            int vec = vecini.first;
            int cost = vecini.second;

            if(dist[nod]+cost < dist[vec]){
                dist[vec] = dist[nod] + cost;
                if(!inCoada[vec]){
                    coada.push(vec);
                    inCoada[vec] = true;
                }
            }
        }
    }


    return make_pair(dist, false);

}



int Graf::bfsMaxflow(int s, int d, vector<int>& parent, vector<vector<int>>& capacitate, vector<vector<int>>& flux,
                     vector<bool>& viz){


    for(int i = 1; i<=nrNoduri; i++){
        viz[i] = false;
    }
    viz[s] = true;
    queue<int> q;
    q.push(s);

    while(!q.empty()){
        int act = q.front();
        q.pop();
        if(act != d)
        for(int next : nod[act]){
            if(capacitate[act][next] == flux[act][next] || viz[next])
                continue;

            viz[next] = true;
            q.push(next);
            parent[next] = act;
        }
    }

    return viz[d];
}


int Graf::maxflow(int s, int d, vector<vector<int>> &capacitate){
    vector<int> parent(nrNoduri+1, 0);
    vector<vector<int>> flux(nrNoduri+1, vector<int>(nrNoduri+1, 0));
    vector<bool> viz(nrNoduri+1, false);
    int flow;

    for(flow = 0; bfsMaxflow(s, d, parent, capacitate, flux, viz);){
        for(int act : nod[d]){
            if(flux[act][d] == capacitate[act][d] || viz[act] == false)
                continue;

            parent[d] = act;
            int fmin = INT_MAX;
            for(int nod = d; nod != s; nod = parent[nod]){
                fmin = min(fmin, capacitate[parent[nod]][nod] - flux[parent[nod]][nod]);
            }

            if(fmin == 0) continue;

            for(int nod = d; nod != s; nod = parent[nod]){
                flux[parent[nod]][nod] += fmin;
                flux[nod][parent[nod]] -= fmin;
            }
            flow += fmin;
        }
    }

    return flow;
}




vector<vector<int>> Graf::royfloyd(int n, vector<vector<int>> dist){

    for(int k = 1; k <= n; k++){
        for(int i =1; i <=n; i++){
            for(int j = 1; j<= n; j++){
                if(dist[i][k] + dist[k][j] < dist[i][j] && dist[i][k] != INT_MAX && dist[k][j] != INT_MAX){
                    dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
    }

    return dist;
}

int Graf::darb(){
    queue<int> q;
    vector<int> dist(nrNoduri+1, 0);
    vector<bool> viz(nrNoduri+1, false);

    viz[1]= true;
    q.push(1);
    int last;

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

        last = cur;

        for(auto vec : nod[cur]){
            if(!viz[vec]){
                viz[vec] = true;
                q.push(vec);
            }

        }
    }

    replace(viz.begin(), viz.end(), true, false);

    q.push(last);
    viz[last] = true;
    dist[last] = 1;

    int maxi = 1;

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

        last = cur;

        for(auto vec : nod[cur]){
            if(!viz[vec]){
                dist[vec] = dist[cur] + 1;
                maxi = max(maxi, dist[vec]);
                viz[vec] = true;
                q.push(vec);
            }

        }
    }

    return maxi;
}


void rezolvareBFS(){
    vector<pair<int, int>> muchi;
    int n, m, s;
    fin>>n>>m>>s;
    for(int i = 1; i <= m; i++){
        int x, y;
        fin>>x>>y;
        muchi.push_back(make_pair(x, y));
    }
    graf.citire(n, m, muchi);
    vector<int> sol = graf.BFS(s);
    for(int i = 1; i <= n; i++){
        fout<<sol[i]<<" ";
    }

    graf.goleste();
}

void rezolvareDFS(){
    vector<pair<int, int>> muchi;
    int n, m;
    fin>>n>>m;
    for(int i = 1; i <= m; i++){
        int x, y;
        fin>>x>>y;
        muchi.push_back(make_pair(x, y));
    }
    graf.citire(n, m, muchi, false);

    int res = graf.DFS();
    fout<<res;

    graf.goleste();
}

void rezolvareBiconexe(){
    vector<pair<int, int>> muchi;
    int n, m;
    fin>>n>>m;
    for(int i = 1; i <= m; i++){
        int x, y;
        fin>>x>>y;
        muchi.push_back(make_pair(x, y));
    }
    graf.citire(n, m, muchi, false);

    vector<vector<int>> sol = graf.compBiconexe();
    int nrComp = sol.size();
    fout<<nrComp<<'\n';
    for(int i = 0; i < nrComp; i++)
    {
        for(auto nod : sol[i])
            fout<<nod<<' ';
        fout<<'\n';
    }

    graf.goleste();
}

void rezolvareCTC(){
    vector<pair<int, int>> muchi;
    int n, m;
    fin>>n>>m;
    for(int i = 1; i <= m; i++){
        int x, y;
        fin>>x>>y;
        muchi.push_back(make_pair(x, y));
    }
    graf.citire(n, m, muchi);
    vector<vector<int>> sol = graf.CTC();
    fout<<sol.size()<<'\n';
    for(auto comp : sol){
        for(auto nod : comp)
            fout<<nod<<' ';
        fout<<'\n';
    }
    graf.goleste();
}

void rezolvareST(){
    vector<pair<int, int>> muchi;
    int n, m;
    fin>>n>>m;
    for(int i = 1; i <= m; i++){
        int x, y;
        fin>>x>>y;
        muchi.push_back(make_pair(x, y));
    }
    graf.citire(n, m, muchi);

    vector<int> sol = graf.ST();
    for(auto nod : sol)
        fout<<nod<<' ';

    graf.goleste();
}

void rezolvareHH(){
    int n;
    vector<int> grade;
    fin>>n;
    for(int i = 1; i <= n; i++)
    {
        int x;
        fin>>x;
        grade.push_back(x);
    }

    bool sol = graf.HavelHakimi(grade);

    if(sol) fout<<"Da";
    else fout<<"Nu";
}

void rezolvareMC(){
    vector<pair<int, int>> muchi;
    int n, m;
    fin>>n>>m;
    for(int i = 1; i <= m; i++){
        int x, y;
        fin>>x>>y;
        muchi.push_back(make_pair(x, y));
    }
    graf.citire(n, m, muchi, false);
    vector<vector<int>> sol = graf.muchiCritice();
    for(auto muchie : sol){
        for(auto nod : muchie)
            fout<<nod<<" ";
        fout<<"\n";
    }

    graf.goleste();
}

void rezolvareAPM(){
    vector<pair<int, pair<int, int>>> muchi;
    int n, m;
    fin>>n>>m;
    for(int i = 1; i<= m; i++){
        int x, y, cost;
        fin>>x>>y>>cost;

        muchi.push_back(make_pair(cost, make_pair(x, y)));
    }

    graf.citireCosturi(n, m, muchi, false);
    vector<pair<int, pair<int, int>>> results = graf.apmPrim();

    int sum = 0;
    for(auto res : results){
        sum+= res.first;
    }
    fout<<sum<<"\n"<<results.size()<<"\n";

    for(auto res : results){
        fout<<res.second.first<<" "<<res.second.second<<"\n";
    }

}

void rezolvareDisjoint(){
    int n, m;
    fin>>n>>m;
    vector<int> paduri;
    paduri.assign(n+1, 0);
    for(int i = 1; i<=n; i++)
        paduri[i] = i;

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

        if(cod == 1)
            graf.disjoint1(x, y, paduri);

        if(cod == 2){
            bool res = graf.disjoint2(x, y, paduri);
            if(res) fout<<"DA\n";
            else fout<<"NU\n";
        }

    }
}


void rezolvareDijkstra(){
    int n, m;
    vector<pair<int, pair<int, int>>> muchi;

    fin>>n>>m;

    for(int i = 1; i <= m; i++){
        int a,b,c;
        fin>>a>>b>>c;

        muchi.push_back(make_pair(c, make_pair(a,b)));
    }

    graf.citireCosturi(n, m, muchi);

    muchi.clear();

    auto res = graf.dijkstra();

    for(int i = 2; i<=n; i++)
        fout<<res[i]<<" ";
}

void rezolvareBellmanFord(){
    int n, m;
    vector<pair<int, pair<int, int>>> muchi;

    fin>>n>>m;

    for(int i = 1; i <= m; i++){
        int a,b,c;
        fin>>a>>b>>c;

        muchi.push_back(make_pair(c, make_pair(a,b)));
    }

    graf.citireCosturi(n, m, muchi);

    muchi.clear();

    auto results = graf.bellmanFord(1);

    if(results.second) fout<<"Ciclu negativ!\n";
    else{
        for(int i = 2; i<=n; i++)
            fout<<results.first[i]<<" ";
    }


}

void rezolvareMaxFlow(){

    int n, m;
    fin>>n>>m;

    graf.setNrNoduri(n);
    graf.setNrMuchi(m);

    vector<vector<int>> capacitati(n+1, vector<int>(n+1, 0));
    for(int i = 1; i <= m; ++i){
        int x, y, z;
        fin>>x>>y>>z;
        graf.addMuchie(x, y);
        graf.addMuchie(y, x);
        capacitati[x][y] = z;
    }

    int res = graf.maxflow(1, n, capacitati);
    fout<<res;
}


void rezolvareRoyFloyd(){
    int n;
    vector<vector<int>> matAd(NMAX, vector<int>(NMAX, 0));
    fin>>n;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            fin>>matAd[i][j];
            if(i != j && matAd[i][j] == 0)
                matAd[i][j] = INT_MAX;
        }
    }

    auto dist = graf.royfloyd(n, matAd);

    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(dist[i][j] == INT_MAX) fout<<0<<" ";
            else fout<<dist[i][j]<<" ";
        }
        fout<<"\n";
    }

}

void rezolvareDarb(){
    int n;
    vector<pair<int, int>> muchi;
    fin>>n;
    for(int i = 1; i < n; i++){
        int x, y;
        fin>>x>>y;
        muchi.push_back(make_pair(x, y));
    }

    graf.citire(n, n-1, muchi, false);

    int sol = graf.darb();
    fout<<sol;
}

int main(){
    rezolvareBiconexe();
}