Cod sursa(job #2823079)

Utilizator lolotbogdanLolot Stefan-Bogdan lolotbogdan Data 26 decembrie 2021 21:06:18
Problema Ciclu Eulerian Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>

using namespace std;

class Disjoint_set
{
	int noduri;
	vector<int>tata; // vector in care sunt stocati reprezentantii componentelor/arborilor(reprezentantul arborelui este radacina sa)
	vector<int>h; // vector in care este stocata inaltimea arborilor

public:
	Disjoint_set(int n);
	void initializare(); // initializarea vectorului de tati/reprezentanti si a vectorului de inaltimi
	int reprezentant(int varf); // determinarea radacinii arborelui care contine varf
	void reuneste(int varf1, int varf2); // reuniunea componentelor care contin varf1 si varf2
	void solve_paduri_de_multimi_disjuncte(ifstream& f, ofstream& o);

};

Disjoint_set::Disjoint_set(int n)
{
	noduri = n;
}

void Disjoint_set::initializare()
{
	tata.resize(noduri + 1, 0);
	h.resize(noduri + 1, 0);
}

int Disjoint_set::reprezentant(int varf)
{
	while (tata[varf] != 0)
		varf = tata[varf];

	return varf;
}

void Disjoint_set::reuneste(int varf1, int varf2)
{
	int rv1, rv2;

	rv1 = reprezentant(varf1);
	rv2 = reprezentant(varf2);

	if (h[rv1] > h[rv2]) // reuniunea se face in functie de inaltimea arborilor(arborele cu inaltime mai mica devine subarbore al radacinii celuilalt arbore)
		tata[rv2] = rv1;

	else
	{
		tata[rv1] = rv2;
		if (h[rv1] == h[rv2])
			h[rv2] ++;
	}
}

void Disjoint_set::solve_paduri_de_multimi_disjuncte(ifstream& f, ofstream& o)
{
	int nr_operatii;

	f >> nr_operatii;

	initializare();

	for (int i = 0; i < nr_operatii; i++)
	{
		int cod, x, y;

		f >> cod >> x >> y;

		if (cod == 1)
			reuneste(x, y);

		else
		{
			if (reprezentant(x) == reprezentant(y))
				o << "DA" << "\n";
			else
				o << "NU" << "\n";
		}
	}

}

class Graf
{
	int noduri, muchii;

	bool ciclu_eulerian(vector<vector<int>>& vecini, vector<int>& grade, vector<int>& componente_ciclu_eulerian);

public:
	Graf(int n, int m);
	void solve_ciclu_eulerian(ifstream& f, ofstream& o);

};

Graf::Graf(int n, int m)
{
	noduri = n;
	muchii = m;
}


bool Graf::ciclu_eulerian(vector<vector<int>>& vecini, vector<int>& grade, vector<int>& componente_ciclu_eulerian)
{
	for (int i = 1; i <= noduri; i++) // verific daca avem noduri de grad impar
		if (grade[i] % 2)
			return 0;

	int varf = 1; // cautam primul nod cu grad != 0

	while (varf <= noduri && grade[varf] == 0)
		varf++;

	if (varf == noduri + 1) // toate varfurile au gradul 0
		return 1;

	stack<int>st;
	st.push(varf);
	while (st.size())
	{
		varf = st.top();

		if (vecini[varf].size() == 0)
		{
			componente_ciclu_eulerian.push_back(varf);
			st.pop();
		}
		else
		{
			int varf2 = vecini[varf][0];
			vecini[varf].erase(vecini[varf].begin());

			for (int j = 0; j < vecini[varf2].size(); j++)
				if (vecini[varf2][j] == varf)
				{
					vecini[varf2].erase(vecini[varf2].begin() + j);
					break;
				}
			st.push(varf2);
		}

	}

	for (int i = 1; i <= noduri; i++)
		if (vecini[i].size())
			return 0;
}


void Graf::solve_ciclu_eulerian(ifstream& f, ofstream& o)
{
	vector<vector<int>>vecini(noduri + 1); // liste de adiacenta
	vector<int>grade(noduri + 1, 0); // vector in care sunt stocate gradele varfurilor
	vector<int>componente_ciclu_eulerian; // vector in care sunt stocate extremitatile muchiilor ce alcatuiesc ciclul eulerian(acolo unde exista unul)

	for (int i = 0; i < muchii; i++)
	{
		int x, y; // extremitatile unei muchii

		f >> x >> y;

		vecini[x].push_back(y);
		vecini[y].push_back(x);

		grade[x]++;
		grade[y]++;
	}

	if (ciclu_eulerian(vecini, grade, componente_ciclu_eulerian))
		for (int i = 0; i < componente_ciclu_eulerian.size() - 1; i++)
			o << componente_ciclu_eulerian[i] << " ";
	//cout << 1;
	else
		o << -1;
}

int main()
{
	ifstream f("ciclueuler.in");
	ofstream o("ciclueuler.out");

	int noduri, muchii;

	f >> noduri >> muchii;

	Graf g(noduri, muchii);

	g.solve_ciclu_eulerian(f, o);

	return 0;
}