Cod sursa(job #1549572)

Utilizator BugirosRobert Bugiros Data 12 decembrie 2015 14:54:15
Problema Ciclu Eulerian Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.62 kb
#include <fstream>
#include <vector>
#include <stack>
using namespace std;

const int MAXN = 100005;

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

vector<int> vecini[MAXN];
vector<int> ciclu;
int grad[MAXN];
int n;

void citire()
{
    int m;
    int a,b;
    in >> n >> m;
    for (int i = 1;i <= m;++i)
    {
        in >> a >> b;
        vecini[a].push_back(b);
        ++grad[b];
        vecini[b].push_back(a);
        ++grad[a];
    }
}

int coada[MAXN] = {0};
int p = 1,q = 1;
bool vizitat[MAXN] = {0};

bool conex()
{
    coada[1] = 1;
    vizitat[1] = 1;
    while(p <= q)
    {
        int nod = coada[p];
        ++p;
        for (unsigned int i = 0;i < vecini[nod].size();++i)
        {
            int vecin = vecini[nod][i];
            if (!vizitat[vecin])
            {
                vizitat[vecin] = true;
                coada[++q] = vecin;
            }
        }
    }

    for (int i = 1;i <= n;++i)
        if (!vizitat[i])
            return false;
    return true;
}

//pentru a fi eulerian trebuie sa fie conex(intre oricare doua noduri sa existe drum)
//si trebuie ca toate nodurile sa aiba grad par
bool eulerian()
{
    if (!conex())
        return false;
    for (int i = 1;i <= n;++i)
        if (grad[i] % 2 == 1)
            return false;
    return true;
}


//optimizat cu faptul ca b este ultimul vecin a lui a
void sterge(int a, int b)
{
    unsigned int i = 0;
    /*while (vecini[a][i] != b)
        ++i;
    vecini[a].erase(vecini[a].begin() + i);*/
    vecini[a].pop_back();

    //i = 0;
    while(vecini[b][i] != a)
        ++i;
    vecini[b].erase(vecini[b].begin() + i);
}


/*
implementare iterativa a pseudocodului:

euler (nod v)
    cat timp (v are vecini)
        w = un vecin aleator al lui v
        sterge_muchie (v, w)
        euler (w)
    sfarsit cat timp
    adauga v la ciclu
*/
stack<int> stiva;

void generare_ciclu()
{
    stiva.push(1);
    while(!stiva.empty())
    {
        int nod = stiva.top();
        if (vecini[nod].size() > 0)
        {
            int vecin = vecini[nod][vecini[nod].size() - 1];
            sterge(nod,vecin);
            stiva.push(vecin);
        }
        else
        {
            ciclu.push_back(nod);
            stiva.pop();
        }
    }
}


int main()
{
    citire();
    if (!eulerian())
        out << "-1";
    else
    {
        generare_ciclu();
        for (unsigned int i = 0;i < ciclu.size() - 1;++i)
            out << ciclu[i] << ' ';
        out << '\n';//fara ultimul element, asa e cerinta
    }
    return 0;
}