Pagini recente » Cod sursa (job #1546216) | Cod sursa (job #1763267) | Cod sursa (job #533529) | Cod sursa (job #2326246) | Cod sursa (job #2139042)
// 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 (nu indecsi de muchii)
// deoarece e multigraf, un vecin poate sa apara de mai multe ori
/* 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;
}