Cod sursa(job #2139029)

Utilizator Dddarius95Darius-Florentin Neatu Dddarius95 Data 22 februarie 2018 00:32:13
Problema Ciclu Eulerian Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 3.12 kb
// Ciclu eulerian - O(N+M) - ITERATIV
#include <fstream>
#include <vector>
#include <algorithm>
#include <stack>
#include <bitset>

#define NMAX 100009
#define pb push_back

using namespace std;

ifstream f("ciclueuler.in");
ofstream g("ciclueuler.out");
 
int N,M,x,y;
vector<int> G[NMAX], Cycle;
stack<int> st;
bitset<NMAX> used; // ca sa pot verifica ca am atins tot graful

// G[node] = lista de adiacenta a lui node
// in care vom pune noduri
// deoarece e multigraf, un vecin poate sa apara de mai multe ori
//(atentie! nu mai stocam indici de muchii)
/* ex. 
1 2
2 1
1 3
3 1
2 3

G arata asa
1| 2, 2, 3, 3
2| 1, 1, 3
3| 1, 1, 2

*/ 

inline int IsEulerian() {
    for(int i = 1; i <= N; ++i) {
        if(G[i].size() % 2 == 1) {
            return 0;
        }
    }
    return 1;
}
 
// in varianta iterativa sterg la propriu muchiile!!!
// de aceea daca initial G[i].size() > 0 (graful era mai mare ca 0)
// ulterior pot avea G[i].size() == 0
void GetCycle(int S) {
    st.push(S); // pun in stiva nodul de start

    while(!st.empty()) {     // cat timp stiva nu e goala <=> nu s-a terminat lantul de apeluri recursive
        int node = st.top(); // in apelul curent, node este ultimul nod in care am intrat
                             // adica cel din varf
        used[node] = 1;      // am vizitat cel putin o data node 
        
        if (G[node].size() > 0) {      // daca node inca mai are muchii incidente
            int last = G[node].back(); // (adica vecini in lista - un vecin poate aparea de mai multe ori)
                                       // atunci aleg sa vizitez ultimul vecin

            st.push(last);             // pun vecinul in stiva <=> apelez recursiv DFS(last) 
            G[node].pop_back();        // sterg la propriu pe last din lista lui node

            // deoarece graful este neorientat, trebuie sa sterg si pe node din lista lui last

            // 1. it = iterator din lista lui last, care indica catre node
            // (adica l-am gasit - *it == node)
            auto it = find(G[last].begin(), G[last].end(), node);
            
            // 2. sterg pe node <=> sterg elementul indicat de it
            G[last].erase(it);
        } else {
            // aici se intra cand node nu mai are vecini in lista
            // adica i-am vizitat si sters pe toti
            // (locul asta e locul de dupa for din DFS)

            Cycle.pb(node); // adaug pe node la ciclu
            st.pop();       // se incheie DFS(node), deci il sterg din varf
                            // ca sa pot reveniin DFS(parinte), iar parinte sa
                            // fie in varful stivei (inainte de pop parinte era sub node)
        }
    }
}
 
int main() {
    f >> N >> M;

    for (int i = 1; i <= M; ++i) {
        int x, y;
        f >> x >> y;

        G[x].pb(y);
        G[y].pb(x);
    }

    if (!IsEulerian()) {
        g << -1 << "\n";
        return 0;
    }
    
    GetCycle(1);
    for (int i = 1; i <= N; ++i) {
        if (!used[i]) {
            g << -1 << "\n";
            return 0;
        }
    }

    for (auto &node : Cycle) {
        g << node << ' ';
    }
    g << '\n';
    
    f.close();g.close();
    return 0;
}