Cod sursa(job #999595)

Utilizator 2dorTudor Ciurca 2dor Data 20 septembrie 2013 22:02:37
Problema Ciclu Eulerian Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.1 kb
#include <fstream>
#include <list>
#include <stack>
#include <queue>
#include <vector>
using namespace std;

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

const int MAXN = 100005;
int N, M, a, b;

list<int> graph[MAXN];
queue<int> coada;//folosita pentru BFS
stack<int> stiva;
vector<int> circuit;
int degree[MAXN];
bool visited[MAXN];

void read() {
    fin >> N >> M;
    for (int i = 0; i < M; ++i) {
        fin >> a >> b;
        degree[a]++; degree[b]++;//cresc gradul
        graph[a].push_back(b);
        graph[b].push_back(a);
    }

}

void BFS() {
    int node;
    coada.push(1);
    list<int>::iterator it;
    do {
        node = coada.front();
        coada.pop();
        for (it = graph[node].begin(); it != graph[node].end(); ++it)
            if (!visited[*it]) {
                visited[*it] = true;
                coada.push(*it);
            }
    }while (!coada.empty());
}

bool connex() {
    BFS();
    for (int i = 1; i <= N; ++i)
        if (visited[i] == false)
            return false;//gasim nod nevizitat => graful nu este conex
    return true;
}

bool eulerian() {//este graful eulerian?
    if (!connex())//conditia 1: graful este conex
        return false;
    else
        for (int i = 1; i <= N; ++i)
            if (degree[i] % 2 == 1)
                return false;//conditia 2: toate gradele nodurilor sa fie pare
    return true;//daca ambele conditii sunt verificate, inseamna ca graful este eulerian
}

void sterge(int node, int neighbour) {
    graph[node].pop_front();//sterg sageata din node -> neighbour
    list<int>::iterator it;
    for (it = graph[neighbour].begin(); it != graph[neighbour].end(); ++it)//caut neighbour -> node
        if (*it == node) {//cand gasesc
            graph[node].erase(it);//sterg; it = pointer catre node
            break;//opresc cautarea
        }
}

void euler(int node) {//lucrez cu o componenta circulara disjuncta (fata de alte componente)
    int neighbour;
    while (!graph[node].empty()) {//pentru cazul in care avem self-loops, repetam.
        //daca node nu mai are vecini, stim ca am ajuns in root, deci am inchis circuitul
        //asa ca incercam sa deschidem un alt circuit (care urmeaza sa fie integrat)
        //dintr-un nod cu vecini (daca nu gasim astfel de noduri, terminam; vezi solve())
        neighbour = graph[node].front();
        stiva.push(node);
        sterge(node, neighbour);//sterg muchia dintre node si neighbour
        node = neighbour;
    }
}

void solve() {
    int node = 1;
    do {
        euler(node);
        node = stiva.top();
        stiva.pop();
        circuit.push_back(node);//pentru vizibilitate, copiem nodurie circuitului intr-un vector
    }while (!stiva.empty());
}

void write() {
    vector<int>::iterator it;
    for (it = circuit.begin(); it != circuit.end(); ++it)
        fout << *it << ' ';
}

int main() {
    read();
    if (eulerian()) {
        solve();
        write();
    }else {
        fout << -1;
    }
    fout << '\n';
    fin.close();
    fout.close();
    return 0;
}