Cod sursa(job #2822051)

Utilizator MihaiBirsanMihai Birsan MihaiBirsan Data 23 decembrie 2021 15:11:22
Problema Ciclu Eulerian Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 11.19 kb
#include <bits/stdc++.h>

#define Nmax 100010

using namespace std;

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


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

class Graf
{
private:
    vector<vector<int>> gr;   //graf -> lista de adiacenta
    vector<vector<int>> gr_t; //graf transpus
    int par[Nmax];
    int dim[Nmax];
    vector<int> topo;
    int dist[Nmax] = {-1};
    int viz[Nmax] ;
    int n;
    int m;
    int nr_componente_conexe = 0;

public:
    Graf(): n(0), m(0)
    {

    }

    Graf(int x, int y = 0): n(x), m(y)
    {

    }

    Graf(int x, int y, const vector<vector<int>>& v): n(x), m(y), gr(v)
    {

    }
    //dezvizitatam toate nodurile
    void nevizitate()
    {
        for(int i = 1; i <= n; i++)
            viz[i] = 0;
    }
    //bfs
    void BFS(int start)
    {
        int c[Nmax];
        int pr, ul;
        pr = 0;
        ul = -1;
        int n_curent;
        dist[start] = 0;
        c[++ul] = start;
        while(pr <= ul)
        {
            n_curent = c[pr++];
            for(auto i:gr[n_curent]) //verificam toti vecinii nodului curent
                if(dist[i] == -1)
                {
                    dist[i] = dist[n_curent] + 1;
                    c[++ul] = i;
                }
        }
    }
    //dfs
    void DFS(int x)
    {
        viz[x] = nr_componente_conexe;
        for(int i = 0; i < gr[x].size(); ++i)
        {
            if(viz[gr[x][i]] == 0)
            {
                viz[gr[x][i]] = 1;
                DFS(gr[x][i]);
            }
        }
    }
    //sortare topologica
    void sortare_topologica(int x)
    {
        viz[x] = 1;
        for(int i = 0; i < gr[x].size(); ++i)
        {
            if(viz[gr[x][i]] == 0)
                sortare_topologica(gr[x][i]);
        }
        topo.push_back(x);
    }

    //Componente tare conexe
    void DFS2(int x,int ct,vector<vector<int>> ctc,  int comp[])
    {
        viz[x] = 1;
        comp[x] = ct;
        ctc[ct].push_back(x);
        for(int i = 0; i< gr_t[x].size(); i++)
        {
            if(viz[gr_t[x][i]] == 0)
            {
                DFS2(gr_t[x][i],ct,ctc,comp);
            }
        }
    }

    void componenteTareConexe(int ct, int comp[], const vector<vector<int>>& ctc)
    {
        nevizitate();
        for(int i=1;i<=n;++i)
        {
            if(viz[i] == 0)
            {
                sortare_topologica(i);
            }
        }
        reverse(topo.begin(), topo.end());
        for(auto i:topo)
        {
            if(comp[i] == 0)
            {
                ct += 1;
                DFS2(i, ct, ctc, comp);
            }
        }
    }
    //Havel Hakimi
    bool HavelHakimi(vector<int> &grade)
    {
        sort(grade.begin(), grade.end(), greater<>());
        while(grade.size() > 0)
        {
            if(grade[0] + 1 > grade.size())
                return false;

            for(int i = 1; i <= grade[0]; i++)
            {
                grade[i] -= 1;
                if(grade[i] < 0)
                {
                    return false;
                }
            }
            grade.erase(grade.begin());
            sort(grade.begin(), grade.end(), greater<>());
        }
        return true;
    }
    //Paduri de multimi disjuncte
    int findd(int x)
    {
        while(x != par[x])
        {
            x = par[x];
        }
        return x;
    }

    void unite(int x, int y)
    {
        x = findd(x);
        y = findd(y);
        if(dim[x] >= dim[y])
        {
            par[y] = x;
            dim[x] += dim[y];
        }
        else
        {
            par[x] = y;
            dim[y] += dim[x];
        }
    }

    void init()
    {
        for(int i=1; i<=n; i++)
        {
            par[i] = i;
            dim[i] = 1;
        }
    }

    //Arbore partial de cost minim -> folosim algoritmul kruskal
    vector<pair<int, pair<int, int>>> kruskal(vector<pair<int, pair<int, int>>>& muchii)
    {
        vector<pair<int, pair<int, int>>> subgr;
        sort(muchii.begin(), muchii.end());
        init();
        for(auto &muchie : muchii)
        {
            if(findd(muchie.second.first) != findd(muchie.second.second))
            {
                unite(muchie.second.first, muchie.second.second);
                subgr.push_back({muchie.first, {muchie.second.first, muchie.second.second}});
            }
        }
        return subgr;
    }

    //Diametrul unui arbore
    void dfsParcurgere(int x, int d, int &dmax, int &nmax)
    {
        if(d > dmax)
        {
            dmax = d;
            nmax = x;
        }
        viz[x] = 1;
        for(auto k:gr[x])
        {
            if(viz[k] == 0)
            {
                dfsParcurgere(k, d+1, dmax, nmax);
            }
        }
    }

    int diamentru()
    {
        int nmax = 0, dmax = 0;
        dfsParcurgere(1, 0, dmax, nmax);
        int n1 = nmax;
        nevizitate();
        dmax = 0;
        nmax = 0;
        dfsParcurgere(n1, 0, dmax, nmax);
        return dmax + 1;
    }

    //Fluxul maxim
    //c -> capacitatea muchiei x y
    //f -> cat flux este pompar pe muchia x,y
    /*
    bool fluxMaxim(int s, int d, vector<vector<int>> &c, vector<vector<int>> &f, vector<int> &parent)
    {
            queue<int> q;
            vector<bool> vis(n + 1);
            int current;

            q.push(s);
            vis[s] = true;
            parent[s] = -1;

            while(!q.empty())
            {
                current = q.front();
                q.pop();
                vis[current] = true;
                for(auto &w: gr[current])
                {
                    if(!vis[w] && c[current][w] - f[current][w])
                    {
                        parent[w] = current;
                        q.push(w);
                    }
                }
            }
            return vis[d];
    }
    */

    void royFloyd(int c[][101])
    {
        int i,j,k;
        for( k = 1; k <= n; k++ )
        {
            for( i = 1; i <= n; i++ )
            {
                for( j = 1; j <= n; j++ )
                {
                    //if (c[i][k] && c[k][j])
                    if (c[i][j] > c[i][k] + c[k][j])
                        c[i][j] = c[i][k] + c[k][j];
                }
            }
        }
    }



    void ciclu_Euler(int start, vector<pair<int,int>> g[], vector<int> &ciclu)
    {
        stack<int> s;
        s.push(start); //adaugam nodul de la care pornim in stiva
        while(!s.empty()) //cat timp avem elem in stiva
        {
            int n = s.top();
            if(!g[n].empty())
            {
                int vecin = g[n].back().second;
                int nr = g[n].back().first; //nr pentru muchia respectiva
                g[n].pop_back();
                if(!viz[nr])
                {
                    viz[nr] = 1;
                    s.push(vecin);
                }
            }
            else
            {
                ciclu.push_back(n);
                s.pop();
            }
        }
    }

    void exista_ciclu_Euler(vector<pair<int,int>> g[])
    {
        vector<int> ciclu;
        for(int i = 0; i <= n; i++)
    {
        if(g[i].size() % 2 == 1)
        {
            fout << "-1";
            return ;
        }
    }
    ciclu_Euler(1, g, ciclu);
    for(int i = 0; i < ciclu.size() - 1; i++)
    {
        fout << ciclu[i] << ' ';
    }
    }

};

int main()
{
    int n, m, x, y;

    vector<pair<int,int>> grf[n+10]; //folosim grf ca si graf care retine in plus si numarul muchiei
    fin >> n >> m;
    for(int i = 1; i <= m; i++)
    {
        fin >> x >> y;
        grf[x].emplace_back(i,y); // adaugam la sfarsitul vectorului
        grf[y].emplace_back(i,x);
    }
    Graf graf(n,m);
    graf.exista_ciclu_Euler(grf);
    return 0;

    //roy-floyd
    /*
    int n, cost[101][101] ;//={1000001};
    fin >> n;
    Graf graf(n);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            fin >> cost[i][j];
            if(cost[i][j] == 0 && i != j)
                cost[i][j] = 1000001;
        }
    }
    graf.royFloyd(cost);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            if(cost[i][j] == 1000001)
                fout << 0 << ' ';
            else
                fout << cost[i][j] << ' ';

        }
        fout << "\n";
    }
    */

    //Fluxul maxim
    /*
    int n,m,x,y,cost;
    vector<vector<int>> c;
    vector<vector<int>> f;
    vector<int> parent;
    int raspuns = 0;
    fin >> n >> m;
    vector<vector<int>> v(n + 1);
    for(int i = 1; i < m; i++)
    {
        fin >> x >> y >> cost;
        v[x].push_back(y);
        c[x][y] = cost;
    }
    Graf graf(n, n-1, v);
    parent.resize(n+1);

    while(fluxMaxim(1,n,c,f,parent))
    {
        // Gasim drumul de la N la 1
        // Gasim muchia cu cap - flux minim
        int current = n;
        int fmin = 1 << 30;
        while (current != 1)
        {
            if (c[parent[current]][current] - f[parent[current]][current] < fmin)
            {
                fmin = c[parent[current]][current] - f[parent[current]][current];
            }

		current = parent[current];
        }

        current = n;
        while(current != 1)
        {
            f[parent[current]][current] += fmin;
            f[current][parent[current]] -= fmin;
            current = parent[current];
        }
        raspuns += fmin;
    }
    fout << raspuns;
    */

    //Diametrul unui arbore /////////////////////////////////////////////////////////////////
    /*
    int n, x ,y;
    fin >> n;
    vector<vector<int>> v(n + 1);
    for(int i = 1; i < n; i++)
    {
        fin >> x >> y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    Graf graf(n, n-1, v);
    int sol = graf.diamentru();
    fout << sol;
    */

    //Paduri de multimi disjuncte////////////////////////////////////////////////////////////
    /*
    int n, m, x ,y, cod;

    fin >> n >> m;
    Graf graf(n, m);
    graf.init();
    for(int i = 1; i <= m; i++)
    {
        fin >> cod >> x >> y;
        if(cod == 1)
        {
            graf.unite(x, y);
        }
        else if(graf.findd(x) == graf.findd(y))
            fout << "DA" << '\n';
        else fout << "NU" << '\n';
    }
    return 0;
    */

    //Arbore partial de cost minim///////////////////////////////////////////////////////////
    /*
    int n, m, x ,y, cost;
    vector<pair<int, pair<int, int>>> muchii;
    fin >> n >> m;
    Graf graf(n, m);
    for(int i = 1; i <= m; i++)
    {
        fin >> x >> y >> cost;
        muchii.push_back({cost,{x,y}});
    }
    int cost_total = 0;
    muchii = graf.kruskal(muchii);
    for(auto muchie : muchii)
    {
        cost_total += muchie.first;
    }
    fout << cost_total << '\n' << n - 1 << '\n';
    for(auto muchie : muchii)
    {
        fout << muchie.second.first << ' ' << muchie.second.second << '\n';
    }
    return 0;
    */
}