Cod sursa(job #2772838)

Utilizator IancuVladIancu Vlad IancuVlad Data 2 septembrie 2021 23:38:25
Problema Ciclu Eulerian Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.73 kb
#include <queue>
#include <iostream>
#include <fstream>
#include <utility>
#include <algorithm>
#include <iterator>
#include <stack>
#include <deque>

//Graf Neorientat:
//Circuit Eulerian - Fiecare nod are grad par
//Drum Eulerian - Fiecare nod are grad par SAU exact 2 noduri au grad impar

//Graf Orientat:
//Circuit Eulerian - Fiecare nod are gradul interior egal cu cel exterior
//Drum Eulerian - Cel mult un nod are `ext - int = 1` si cel mult un nod are 'int - ext = 1' iar toate celelalte au gradele egale
//Ca sa gasesti un drum eulerian (atunci cand circuitul nu exista) trebuie sa incepi de la nodul cu gradul exterior mai mare
//si sa ajungi la nodul cu gradul exterior mai mic
const int NMax = 100010;
std::deque<int> path;
std::vector<int> G[NMax];
bool **visited;
int out[NMax];
int in[NMax];
int N, M;
int S = 0, E = 0;

void read()
{
    std::ifstream input("ciclueuler.in");
    input >> N >> M;
    std::fill(out, out + N +  1, 0);
    std::fill(in, in + N + 1, 0);
    //std::cout << "Initializing visited" << std::endl;
    for (int i = 0; i < M; i++)
    {
        int x, y;
        input >> x >> y;
        G[x].push_back(y);
        out[x]++;
        in[y]++;
    }
    visited = new bool *[N + 1];
    for (int i = 0; i <= N; i++)
    {
        visited[i] = new bool[N + 1];
        for (int j = 0; j <= N; j++)
        {
            visited[i][j] = false;
        }
    }
    //std::cout << "Initialized visited" << std::endl;
    input.close();
    for (int i = 1; i <= N; i++)
    {
        if (out[i] - in[i] == 1)
        {
            if (S == 0)
            {
                S = i;
            }
            else
            {
                S = -1;
                return;
            }
        }
        else if (out[i] - in[i] > 1)
        {
            S = -1;
            return;
        }
        if (in[i] - out[i] == 1)
        {
            if (E == 0)
            {
                E = i;
            }
            else
            {
                E = -1;
                return;
            }
        }
        else if (in[i] - out[i] > 1)
        {
            E = -1;
            return;
        }
    }
}

void dfs(int u)
{
    if (out[u])
        for (int v : G[u])
        {
            if (!visited[u][v])
            {
                visited[u][v] = true;
                out[u]--;
                dfs(v);
            }
        }
    path.push_front(u);
}

int main()
{
    read();
    if (S == 0 && E == 0)
    {
        dfs(1); //Avem circuit eulerian
    }
    else
    {
        if (S > 0 && E > 0)
            dfs(S); //Avem drum eulerian incepand de la S
    }
    std::ofstream out_file("ciclueuler.out");
    std::copy(path.begin(), path.end(), std::ostream_iterator<int>(out_file, " "));
    //std::cout << std::endl;
    return 0;
}