Cod sursa(job #2341447)

Utilizator petru.ciocirlanPetru Ciocirlan petru.ciocirlan Data 11 februarie 2019 20:32:24
Problema Ciclu Eulerian Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.34 kb
#include <fstream>
#include <vector>
#include <stack>
#include <bitset>
using namespace std;

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

const int INF = 0x3f3f3f3f;
const int MAXN = 100000 + 16;
const int MAXM = 500000 + 16;

stack < int > ST;
vector < pair < int, int > > Edge[MAXN];
vector < pair < int, int > > TreeEdge[MAXN], ReturnEdge[MAXN];
int Deg[MAXN], Sol[MAXN];
int N, M, K, start;

void citire();
bool isValid();
void dfs(int);
void createEuler(int);

int main()
{
    citire();
    if(isValid())
    {
        dfs(start);
        createEuler(start);
    }
    else
        fout << "-1\n";

    return 0;
}

bitset < MAXM > VizM;
void createEuler(int rad)
{
    VizM.reset();
    ST.push(rad);

    while(ST.size() < (unsigned)M)
    {
        int nod = ST.top();
        if(!ReturnEdge[nod].empty())
        {
            while(!ReturnEdge[nod].empty() && VizM.test(ReturnEdge[nod].back().second))
                ReturnEdge[nod].pop_back();
            if(ReturnEdge[nod].empty())
                continue;
            int next = ReturnEdge[nod].back().first;
            VizM.set(ReturnEdge[nod].back().second);
            ST.push(next);
        }
        else
        {
            while(!TreeEdge[nod].empty() && VizM.test(TreeEdge[nod].back().second))
                TreeEdge[nod].pop_back();
            int next = TreeEdge[nod].back().first;
            VizM.set(TreeEdge[nod].back().second);
            ST.push(next);
        }
    }

    while(!ST.empty())
    {
        fout << ST.top() << ' ';
        ST.pop();
    }
}

bool VizN[MAXN];
int Return[MAXN], Father[MAXN];
void dfs(int rad)
{
    Return[rad] = INF;
    Father[rad] = 0;

    int level = 0;
    ST.push(rad);
    while(!ST.empty())
    {
        int nod = ST.top();
        VizN[nod] = true;

        while(!Edge[nod].empty() && VizM.test(Edge[nod].back().second))
            Edge[nod].pop_back();

        if(Edge[nod].empty())
        {
            if(Return[Father[nod]] > Return[nod])
                Return[Father[nod]] = Return[nod];
            ST.pop();
            --level;
        }
        else
        {
            int next = Edge[nod].back().first;
            VizM.set(Edge[nod].back().second);
            Edge[nod].pop_back();
            if(VizN[next])
            {
                ++K;
                ReturnEdge[nod].push_back(make_pair(next, K));
                ReturnEdge[next].push_back(make_pair(nod, K));
                Return[nod] = level;
            }
            else
            {
                ++K;
                TreeEdge[nod].push_back(make_pair(next, K));
                TreeEdge[next].push_back(make_pair(nod, K));
                ++level;
                Father[next] = nod;
                ST.push(next);
            }
        }
    }
}

bool isValid()
{
    start = 1;

    int cnt = 0;
    for(int i = 1; i <= N; ++i)
        if(Deg[i]&1)
            ++cnt, start = i;

    if(cnt) //&& cnt != 2)
        return false;

    return true;
}

void citire()
{
    fin >> N >> M;
    for(int i = 1; i <= M; ++i)
    {
        int a, b;
        fin >> a >> b;
        Edge[a].push_back(make_pair(b, i));
        Edge[b].push_back(make_pair(a, i));
        ++Deg[a], ++Deg[b];
    }
}