Cod sursa(job #2815346)

Utilizator MihaiLazar26Lazar Mihai MihaiLazar26 Data 9 decembrie 2021 15:15:07
Problema Diametrul unui arbore Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 20.25 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <climits>

using namespace std;

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

#define NMAX 100001

class Graf{
    vector<int> nod[NMAX];
    vector<pair<int, int>> nodCosturi[1];
    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);
    void actDFS(int S);
    void biconexeDFS(int S, int Tata);

    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);

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));
        }
    }


    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){
    this->coada.push(S);
    this->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){
    setViz(this->nrNoduri, -1);
    actBFS(S);
    return this->viz;
}

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

int Graf::DFS(){
    int componente = 0;
    setViz(nrNoduri, 0);
    for(int i = 1; i <= nrNoduri; i++){
        if(!viz[i]) actDFS(i), ++componente;
    }
    return componente;
}

void Graf::biconexeDFS(int S, int Tata){
    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);
                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(){
    viz.assign(nrNoduri+1, 0);
    nma.assign(nrNoduri+1, 0);
    biconexeDFS(1,0);
    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){
    fill(parent.begin(), parent.end(), -1);
    parent[s] = -2;
    queue<pair<int, int>> q;
    q.push(make_pair(s, INT_MAX));

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

        for(int next : nod[cur]){
            if(parent[next] == -1 && capacitate[cur][next]){
                parent[next] = cur;
                int new_flow = min(flow, capacitate[cur][next]);

                if(next == d) return new_flow;
                q.push(make_pair(next, new_flow));
            }
        }
    }

    return 0;
}


int Graf::maxflow(int s, int d, vector<vector<int>> capacitate){
    int flow = 0;
    vector<int> parent(nrNoduri+1);
    int new_flow;
    while(new_flow = bfsMaxflow(s, d, parent, capacitate)){
        flow += new_flow;
        int cur = d;
        while(cur != s){
            int prev = parent[cur];
            capacitate[prev][cur] -= new_flow;
            capacitate[cur][prev] += new_flow;
            cur = prev;
        }
    }

    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(){
    vector<vector<int>> capacitati(NMAX, vector<int>(NMAX, 0));
    vector<pair<int, int>> muchi;

    int n, m;
    fin>>n>>m;
    for(int i = 1; i <= m; ++i){
        int x, y, z;
        fin>>x>>y>>z;
        muchi.push_back(make_pair(x, y));
        capacitati[x][y] = z;
    }

    graf.citire(n, m, muchi, false);

    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;
    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(){
    rezolvareDarb();
}