Cod sursa(job #608035)

Utilizator vlad.maneaVlad Manea vlad.manea Data 14 august 2011 17:27:05
Problema Ciclu Eulerian Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 1.79 kb
#include <cstdio>

#include <stack>
#include <queue>
#include <list>
#include <bitset>
#include <vector>

#define INFILE "ciclueuler.in"
#define OUTFILE "ciclueuler.out"
#define NMax 100001
using namespace std;

int N, M;
list<int> E[NMax];
vector<int> C(NMax, 0);

void read()
{
	int x, y;
	freopen(INFILE, "r", stdin);
	scanf("%d%d", &N, &M);

	// citesc muchiile
	while (M--)
	{
		scanf("%d%d", &x, &y);

		if (x - y)
		{
			E[x].push_back(y);
			E[y].push_back(x);
		}
		else
			C[x]++;
	}
}

inline bool hasEvenDegrees()
{
	for (int i = 1; i <= N; ++i)
		if (E[i].size() % 2)
			return false;

	return true;
}

inline bool isConnected()
{
	queue<int> Q;
	bitset<NMax> V;
	int x, y, c;
	list<int>::iterator i;

	for (Q.push(c = 1), V.set(1); !Q.empty() && c < N; Q.pop())
		for (i = E[x = Q.front()].begin(); i != E[x].end(); ++i)
			if (!V[y = *i])
			{
				V.set(y);
				++c;
				Q.push(y);
			}

	return N == c;
}

inline bool isEulerian()
{
	return hasEvenDegrees() && isConnected();
}

void write()
{
	freopen(OUTFILE, "w", stdout);
	list<int>::iterator f;
	stack<int> S;
	int i, x, y;
	
	if (!isEulerian())
	{
		printf("-1\n");
		return;
	}

	// adaug primul nod
	S.push(1);

	// simulez recursia
	while (!S.empty())
	{
		// preiau nodul curent
		x = S.top();

		// are fii?
		if (E[x].size() > 0)
		{
			f = E[x].begin();
			y = *f;

			// adaug fiul lui
			S.push(y);

			// distrug legatura dinspre x
			E[x].pop_front();

			// distrug legatura dinspre y
			for (f = E[y].begin(); f != E[y].end(); ++f)
				if (*f == x)
				{
					E[y].erase(f);
					break;
				}
		}
		else
		{
			// scriu buclele
			for (int i = 1; i <= C[x]; ++i)
				printf("%d ", x);

			// elimin nodul curent
			C[x] = 0;
			S.pop();

			// scriu nodul
			if (!S.empty())
				printf("%d ", x);
		}
	}
}

int main()
{
	read();
	write();
	return 0;
}