Cod sursa(job #2806276)

Utilizator ScobiolaRaduScobiola Radu ScobiolaRadu Data 22 noiembrie 2021 14:46:26
Problema Arbore partial de cost minim Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 6.76 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <stack>
#include <list>

using namespace std;

ifstream in("apm.in");
ofstream out("apm.out");

const int maxi = 200001;
const bool problema = 1; //0 pt problema bfs

class Graf
{
private:
    int n, m, s;
    vector<int> v[maxi];

public:
    Graf(bool tip);
    void bfs();                                     //bfs
    void dfs(int nod, int viz[]);                   //nr componente conexe
    void nrconex();                                 //-----
    void dfstop(int nod, int viz[], stack<int> &s); //sortare topologica
    void sortaret();                                //-----
    void ctc();                                     //nr componente tare conexe
    void ordine(int nod, int viz[], stack<int> &s); //-----
    void dfsctc(int nod, int viz[], int ok);        //-----
    Graf trans();                                   //-----
};

class muchiecost
{
public:
    int st, dr, cost;
};

class Grafcost{
    public:
        int n,m;
        muchiecost* muchie;
};

Grafcost* creeazagraf(int n, int m)
{
    Grafcost* g= new Grafcost;
    g->n=n;
    g->m=m;

    g->muchie=new muchiecost[m];
    return g;
}

class subset
{
public:
    int parent;
    int rank;
};

Graf::Graf(bool tip) //true pt orientat
{
    int i;
    muchiecost muchie;
    in >> n >> m;
    if (problema == 0)
        in >> s;
    for (i = 1; i <= m; i++)
    {
        int x, y, c;
        in >> x >> y;
        v[x].push_back(y);
        if (tip == false)
            v[y].push_back(x);
    }
}

void Graf::bfs()
{
    int i;
    int dist[n + 1];
    for (i = 1; i <= n; i++)
        dist[i] = -1;
    dist[s] = 0;
    queue<int> q;
    q.push(s);

    while (!q.empty())
    {
        int nc = q.front();                //nod curent
        for (i = 0; i < v[nc].size(); i++) //parcurgerm vecinii lui nc
        {
            if (dist[v[nc][i]] == -1)
            {
                q.push(v[nc][i]);
                dist[v[nc][i]] = dist[nc] + 1;
            }
        }
        q.pop();
    }

    for (i = 1; i <= n; i++)
        out << dist[i] << " ";
    out.close();
}

void Graf::dfs(int nod, int viz[])
{
    viz[nod] = 1;
    int i;
    for (i = 0; i < v[nod].size(); i++) //parcurgem vecinii nodului, se marcheaza toata componenta conexa ca fiind vizitata
    {
        if (viz[v[nod][i]] == 0)
        {
            dfs(v[nod][i], viz);
        }
    }
}

void Graf::nrconex()
{
    int k = 0, i;
    int viz[n + 1] = {0};
    for (i = 1; i <= n; i++)
        if (viz[i] == 0)
        {
            dfs(i, viz);
            k++;
        }
    out << k;
}

void Graf::dfstop(int nod, int viz[], stack<int> &s)
{
    viz[nod] = 1;
    int i;
    for (i = 0; i < v[nod].size(); i++)
    {
        if (viz[v[nod][i]] == 0)
            dfstop(v[nod][i], viz, s);
    }
    s.push(nod);
}

void Graf::sortaret()
{
    int i;
    stack<int> s;
    int viz[n + 1] = {0};
    for (i = 1; i <= n; i++)
        if (viz[i] == 0)
            dfstop(i, viz, s);

    while (!s.empty())
    {
        out << s.top() << " ";
        s.pop();
    }
}

void Graf::dfsctc(int nod, int viz[], int ok) //afisam dfs incepand din nod
{
    viz[nod] = 1;
    if (ok == 1)
        out << nod << " ";
    int i;
    for (i = 0; i < v[nod].size(); i++)
    {
        if (viz[v[nod][i]] == 0)
            dfsctc(v[nod][i], viz, ok);
    }
}

Graf Graf::trans()
{
    int i;
    Graf g(true);
    for (i = 1; i <= n; i++) //parcurgem nodurile
    {
        vector<int>::iterator j;
        for (j = v[i].begin(); j != v[i].end(); j++) //parcurgem vecinii fiecarui nod
            g.v[*j].push_back(i);                    //in transpusa punem arcul inversat
    }
    return g;
}

void Graf::ordine(int nod, int viz[], stack<int> &s) //punem in stack nodurile dupa timpul de finalizare
{
    viz[nod] = 1;
    for (int i = 0; i < v[nod].size(); i++)
        if (viz[v[nod][i]] == 0)
            ordine(v[nod][i], viz, s);
    s.push(nod);
}

void Graf::ctc()
{
    int i, k = 0, ok = 0;
    stack<int> s;
    stack<int> s2;
    int viz[n + 1] = {0};
    for (i = 1; i <= n; i++)
        if (viz[i] == 0)
            ordine(i, viz, s); //cream stackul cu timpurile de finalizare
    Graf gr = trans();
    for (i = 1; i <= n; i++)
        viz[i] = 0; //reinitializam ca nevizitate pt al doilea dfs
    s2 = s;
    while (!s.empty()) //mai intai doar le numaram
    {
        int nod = s.top();
        s.pop();
        if (viz[nod] == 0)
        {
            gr.dfsctc(nod, viz, ok);
            k++;
        }
    }
    ok = 1;
    out << k << endl;
    for (i = 1; i <= n; i++)
        viz[i] = 0;
    while (!s2.empty()) //parcurgem iar si afisam componentele
    {
        int nod = s2.top();
        s2.pop();
        if (viz[nod] == 0)
        {
            gr.dfsctc(nod, viz, ok);
            out << endl;
        }
    }
}

int find(subset subsets[], int i)
{
    if (subsets[i].parent != i)
        subsets[i].parent = find(subsets, subsets[i].parent);
    return subsets[i].parent;
}

void uniune(subset subsets[], int x, int y)
{
    int xrad = find(subsets, x);
    int yrad = find(subsets, y);
    if (subsets[xrad].rank < subsets[yrad].rank)
        subsets[xrad].parent = yrad;
    else if (subsets[xrad].rank > subsets[yrad].rank)
        subsets[yrad].parent = xrad;
    else
    {
        subsets[yrad].parent = xrad;
        subsets[xrad].rank++;
    }
}

int comp(const void* a, const void* b)
{
    muchiecost* a1=(muchiecost*)a;
    muchiecost* b1=(muchiecost*)b;
    return a1->cost>b1->cost;
}

void kruskal(Grafcost* g)
{
    int n=g->n;
    muchiecost rez[n];
    int e=0,i=0;
    qsort(g->muchie,g->m,sizeof(g->muchie[0]),comp);

    subset* subsets=new subset[(n*sizeof(subset))];
    for(int j=0;j<n;j++)
    {
        subsets[j].parent=j;
        subsets[j].rank=0;
    }

    while(e<n-1&&i<g->m)
    {
        muchiecost urm=g->muchie[i++];
        int x=find(subsets,urm.st);
        int y=find(subsets, urm.dr);
        if(x!=y)
        {
            rez[e++]=urm;
            uniune(subsets,x,y);    
        }
    }
    int mini=0;
    int k=0;
    for(i=0;i<e;i++)
    {
        mini=mini+rez[i].cost;
        k++;
    }
    out<<mini<<endl<<k<<endl;
    for(i=0;i<e;i++)
    {
        out<<rez[i].dr<<" "<<rez[i].st<<endl;
    }

}

int main()
{
    int n,m;
    in>>n>>m;
    Grafcost* g=creeazagraf(n,m);
    int i;
    for(i=0;i<m;i++)
    {
        int x,y,c;
        in>>x>>y>>c;
        g->muchie[i].st=x;
        g->muchie[i].dr=y;
        g->muchie[i].cost=c;
    }
    kruskal(g);

    return 0;
}