Cod sursa(job #2907355)

Utilizator gogurazvanRazvan Gogu gogurazvan Data 29 mai 2022 21:08:18
Problema Arbore partial de cost minim Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 11.66 kb
#include<bits/stdc++.h>

using namespace std;
ifstream in("apm.in");
ofstream out("apm.out");
const int nmax = 100001;

struct muchie_prop{
    int cost;
};
struct pairCompSec {
    constexpr bool operator()(pair<int, int> const& a,pair<int, int> const& b) const noexcept{
        return a.second > b.second;
    }
};

class Graf{
    int n, m;
    vector<pair<int, muchie_prop>>vecin[nmax];


    void recursieDFS(int nod, bool vizitat[]){
        vizitat[nod]=true;
        for(int i=0; i<vecin[nod].size(); ++i)
            if(vizitat[vecin[nod][i].first]==false)
                recursieDFS(vecin[nod][i].first, vizitat);

    }
    void recursieDFSdistante(int nod, int vizitat[],int k){
        vizitat[nod]=k;
        for(int i=0; i<vecin[nod].size(); ++i)
            if(vizitat[vecin[nod][i].first]==-1)
                recursieDFSdistante(vecin[nod][i].first, vizitat,k+1);

    }

    void recursieDFS_sort(int nod, bool vizitat[],stack <int> &s){
        vizitat[nod]=true;
        for(int i=0; i<vecin[nod].size(); ++i)
            if(vizitat[vecin[nod][i].first]==false)
                recursieDFS_sort(vecin[nod][i].first, vizitat,s);

        s.push(nod);

    }



    void recursieCTC(int nod, int vizitat[], int varf[], stack <int> &s, bool scheck[], int &cont,int &nr,int sol[],int &k){

        vizitat[nod]=cont;
        scheck[nod]=true;
        varf[nod]=cont;
        s.push(nod);
        for(int i=0; i<vecin[nod].size(); ++i){
            if(vizitat[vecin[nod][i].first]==-1){
                cont=cont+1;
                recursieCTC(vecin[nod][i].first, vizitat,varf,s,scheck,cont,nr,sol,k);
                varf[nod]=min( varf[nod], varf[ vecin[nod][i].first ] );
            }else if(scheck[vecin[nod][i].first]==true) varf[nod]=min( varf[nod], vizitat[ vecin[nod][i].first ] );
        }
        if( varf[nod] == vizitat[nod] ){
            nr++;
            while(s.top()!=nod){
                sol[k]=s.top(); k++;
                scheck[s.top()]=false;
                s.pop();
            }
            sol[k]=s.top(); k++;
            sol[k]=-1; k++;
            scheck[s.top()]=false;
            s.pop();
        }

    }

    void recursieBC(int nod, int vizitat[], int varf[], stack <int> &s, int &cont, int &nr,int sol[],int &k){

        vizitat[nod]=cont;
        varf[nod]=cont;
        cont++;
        s.push(nod);
        for(int i=0; i<vecin[nod].size(); ++i){
            if(vizitat[vecin[nod][i].first]==-1){

                s.push(nod*(-1));
                recursieBC(vecin[nod][i].first, vizitat,varf,s,cont,nr,sol,k);

                if( varf[ vecin[nod][i].first ] >= vizitat[nod] ){
                    nr++;
                    while(s.top()!=nod && s.top()!=nod*(-1)){
                        if(s.top()>0){ sol[k]=s.top(); k++;}
                        s.pop();
                    }
                    sol[k]=nod; k++;
                    sol[k]=-1; k++;
                }else{
                    varf[nod]=min( varf[nod], varf[ vecin[nod][i].first ] );
                }

            }else varf[nod]=min( varf[nod], vizitat[ vecin[nod][i].first ] );
        }


    }

public:

    Graf(int n, int m){
        this->n=n;
        this->m=m;
    }

    void citireM( bool orient , int nivel_costuri=0){

        for( int i=0; i<m; ++i ){

            muchie_prop pr;

            int a, b, c;
            in >> a >> b;
            if( nivel_costuri>=1 ){
                in>>c;
                pr.cost=c;
            }

            vecin[a].push_back({b,pr});

            if( orient == false ){
                vecin[b].push_back({a,pr});
            }
        }
    }

    void DFS(){

        int nr_comp_conex=0;
        bool vizitat[n];

        for(int i=1;i<=n;++i)
            vizitat[i]=false;

        for(int i=1;i<=n;++i){
            if(vizitat[i]==false){
                recursieDFS(i,vizitat);
                nr_comp_conex++;
            }
        }
        out<<nr_comp_conex;

    }

    void BFS(int s){

        int drum[n+1];

        for(int i=1;i<=n;++i)
            drum[i]=-1;

        drum[s]=0;
        queue <int> poz;
        poz.push(s);

        while(!poz.empty()){
            int nod=poz.front();
            for(int i=0; i<vecin[nod].size(); ++i){
                if( drum[vecin[nod][i].first] == -1 ){
                    poz.push( vecin[nod][i].first );
                    drum[vecin[nod][i].first]=drum[nod]+1;
                }
            }
            poz.pop();
        }

        for(int i=1;i<=n;++i)
            out<<drum[i]<<" ";

    }

    void CTC(){
        int desc[n+1], varf[n+1];
        stack <int> s;
        bool scheck[n+1];
        for(int i=1;i<=n;++i){
            desc[i]=-1;
            varf[i]=-1;
            scheck[i]=false;
        }
        int cont=0,nr=0,solutie[2*n+5], k=0;
        for(int i=1;i<=n;++i){
            if(desc[i]==-1)
                recursieCTC(i,desc,varf,s,scheck,cont,nr,solutie,k);

        }
        out<<nr<<"\n";
        int j=k-2;
        while(j>=0){
            while(solutie[j]!=-1 && j>=0){
                out<<solutie[j]<<" ";
                --j;
            }
            nr--; j--; out<<"\n";
        }

    }

    void BC(){
        int desc[n+1], varf[n+1];
        stack <int> s;
        for(int i=1;i<=n;++i){
            desc[i]=-1;
            varf[i]=-1;
        }
        int cont=0,nr=0,solutie[2*n+5], k=0;
        for(int i=1;i<=n;++i){
            if(desc[i]==-1){
                if(vecin[i].empty()==true){

                    nr++;
                    solutie[k]=i; k++;
                    solutie[k]=-1; k++;
                }else{

                    recursieBC(i,desc,varf,s,cont,nr,solutie,k);
                }
                while(s.empty()!=true) s.pop();
            }

        }
        out<<nr<<"\n";
        int j=k-2;
        while(j>=0){
            while(solutie[j]!=-1 && j>=0){
                out<<solutie[j]<<" ";
                --j;
            }
            nr--; j--; out<<"\n";
        }


    }


    bool HH(){
        int grad[n+3];
        for(int i=1; i<=n;++i)
            in>>grad[i];
        sort(grad+1,grad+n+1,greater<int>());

        int nr0=0;
        for(int i=1; i<=n; ++i){
            if(grad[i]==0) return true;
            if(grad[i]>n-i) return false;
            if(grad[i]==1){
                if((n-i-nr0+1)%2==0) return true;
                else return false;
            }
            for(int j=i+1; j<=i+grad[i]; ++j){

                grad[j]--;
                if(grad[j]<0) return false;
                if(grad[j]==0) nr0++;
            }
            sort(grad+i+1,grad+n+1,greater<int>());
        }
        return true;
    }

    void ST(){
        bool vizitat[n+1];
        stack <int> st;

        for(int i=1; i<=n;++i)
            vizitat[i]=false;
        for(int i=1; i<=n;++i)
            if(vizitat[i]==false)
                recursieDFS_sort(i,vizitat,st);

        while(st.empty()!=true){
            out<<st.top()<<" ";
            st.pop();
        }
    }
    int Darb(){
        int distante[100001];
        for(int i=1;i<=n;++i)
            distante[i]=-1;
        recursieDFSdistante(1,distante,0);
        int nod_mac=1,mac=0;
        for(int i=1;i<=n;++i){
            if(distante[i]>mac)
            {
                mac=distante[i];
                nod_mac=i;
            }
            distante[i]=-1;
        }
        recursieDFSdistante(nod_mac,distante,0);
        for(int i=1;i<=n;++i)
            if(distante[i]>mac)
                mac=distante[i];

        return mac+1;



    }

    void Roy_Floyd(int M[101][101]){
        for(int k=1;k<=n;++k)
            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j){
                    if( (M[i][j] > M[i][k]+M[k][j] || ( M[i][j]==0 && i!=j )) && M[i][k]!=0 && M[k][j]!=0)
                        M[i][j]=M[i][k]+M[k][j];
                }
    }

    void Dijkstra(int start, int dist[]){
        bool viz[n+1];
        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>> > dist_min;
        for( int i=1; i<=n; ++i ){
            viz[i]=false;
            dist[i]=-1;
        }
        int p = start;
        dist[start]=0;

        for( int i=1; i<=n; ++i ){
            viz[p]=true;
            for( int j=0; j< vecin[p].size(); ++j ){
                int nvec = vecin[p][j].first;
                if( !viz[nvec] && ( dist[nvec] == -1  ||  dist[nvec] > dist[p]+ vecin[p][j].second.cost ) ){
                    dist[nvec]= dist[p]+ vecin[p][j].second.cost;
                    dist_min.push( make_pair(dist[nvec], nvec) );
                }

            }

            while( viz[ dist_min.top().second ] && !dist_min.empty() )
                dist_min.pop();
            if(!dist_min.empty()){
                p=dist_min.top().second;
                dist_min.pop();
            }

        }

    }

    void APM(int &cost_m, pair<int,int> muchii_apm[]){

        bool apm[n+1];
        int parent[n+1],pcost[n+1];
        for(int i=0; i<n+1; ++i){
            apm[i]=false;
            pcost[i]=-1;
        }


        priority_queue<pair<int,int>, vector<pair<int,int>>, pairCompSec > dist_min;
        dist_min.push({1,0});

        for(int i=0; i<n; ++i){
            while(apm[dist_min.top().first]==true)
                dist_min.pop();

            int nod=dist_min.top().first;
            cost_m+=dist_min.top().second;
            dist_min.pop();
            muchii_apm[i]={parent[nod],nod};
            apm[nod]=true;
            for(int j=0; j<vecin[nod].size(); ++j){
                if( apm[vecin[nod][j].first]==false ){

                    if(pcost[vecin[nod][j].first]==-1 || vecin[nod][j].second.cost < pcost[vecin[nod][j].first]){
                        parent[vecin[nod][j].first]=nod;
                        pcost[vecin[nod][j].first]=vecin[nod][j].second.cost;
                    }

                    dist_min.push( {vecin[nod][j].first, vecin[nod][j].second.cost} );
                }

            }
        }



    }

    void BellF(int &cost_m, pair<int,int> muchii_apm[]){
        bool apm[n+1];

        int parent[n+1],pcost[n+1];
        for(int i=0; i<n+1; ++i){
            apm[i]=false;
            pcost[i]=-1;
        }

        priority_queue<pair<int,int>, vector<pair<int,int>>, pairCompSec > dist_min;
        dist_min.push({1,0});

        for(int i=0; i<n; ++i){
            while(apm[dist_min.top().first]==true)
                dist_min.pop();

            int nod=dist_min.top().first;
            cost_m+=dist_min.top().second;
            dist_min.pop();
            muchii_apm[i]={parent[nod],nod};
            apm[nod]=true;
            for(int j=0; j<vecin[nod].size(); ++j){
                if( apm[vecin[nod][j].first]==false ){

                    if(pcost[vecin[nod][j].first]==-1 || vecin[nod][j].second.cost < pcost[vecin[nod][j].first]){
                        parent[vecin[nod][j].first]=nod;
                        pcost[vecin[nod][j].first]=vecin[nod][j].second.cost;
                    }

                    dist_min.push( {vecin[nod][j].first, vecin[nod][j].second.cost} );
                }

            }
        }



    }



};




int main()
{
    int n=0,m=0;
    in>>n>>m;
    Graf graf= Graf(n,m);
    graf.citireM(false,1);
    pair<int,int> muchii_apm[n];
    int cost=0;
    graf.APM(cost,muchii_apm);
    out<<cost<<'\n'<<n-1<<'\n';
    for(int i=1; i<n;++i)
        out<<muchii_apm[i].first<<' '<<muchii_apm[i].second<<'\n';

    return 0;
}