Cod sursa(job #689448)

Utilizator mika17Mihai Alex Ionescu mika17 Data 24 februarie 2012 15:16:56
Problema Ciclu Eulerian Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 2.54 kb
#include <fstream>
#include <vector>
#include <stack>
#include <list>
#include <cstdlib>
using std::vector;
using std::list;

struct edge_type
{
	int x,y;
	bool valid;
	edge_type(int _x,int _y,bool _valid) : x(_x) , y(_y), valid(_valid) {}
};


/*
Check if graph has Euler's property
*/

bool isEuler(vector<list<int> > &G,vector<edge_type> & edges,int V,int E)
{
	{
		vector<int> deg(V + 1);
		for(int i = 0; i < E; ++i)
			deg[edges[i].x] ++, deg[edges[i].y] ++;

		for(int i = 1; i <= V; ++i)
			if(deg[i] & 1)
				return false;
	}
	{
		vector<int> Q(V + 1);
		int le = 0, ri = 0;
		vector<bool> vis(V + 1,false);

		int start = rand() % V + 1;
		Q[ri++] = start;
		vis[start] = true;

		while(le < ri)
		{
			int q = Q[le++];

			for(list<int>::iterator i = G[q].begin() ; i != G[q].end(); ++i)
				if(!vis[edges[*i].x]) //parcurg de la y la x muchia
					Q[ri++] = edges[*i].x, vis[edges[*i].x] = true;
				else if(!vis[edges[*i].y]) //parcurg de la x la y muchia
					Q[ri++] = edges[*i].y, vis[edges[*i].y] = true;
		}

		for(int i = 1; i <= V; ++i)
			if(vis[i] == 0)
				return false;
	}

	return true;
}

/*
Fleury's algorithm
//TO DO
*/

/*
Hierholzer's algorithm
*/
vector<int> EulerTour(vector<list<int> > &G,vector<edge_type> & edges,int V,int E)
{
	
	vector<int> tour; //contains indices of edges

	std::stack<int> vertex;
	int start = rand() % V + 1;
	vertex.push(start);
	while(!vertex.empty())
	{
		int v = vertex.top();
		bool found = false;
		for(list<int>::iterator i = G[v].begin(); i != G[v].end();)
		{
			if(edges[*i].valid) //daca n-am folosit deja o data muchia
			{
				if(edges[*i].x == v)
					vertex.push(edges[*i].y);
				else vertex.push(edges[*i].x); //edges[*i].y == v
				
				edges[*i].valid = false;
				G[v].pop_front();
				found = true;

				break;
			} else i =  G[v].erase(i);
			
		}
		if(!found) tour.push_back(vertex.top()),vertex.pop();
	}
	tour.pop_back();
	return tour;
}

int main()
{
	std::ifstream in("ciclueuler.in");
	std::ofstream out("ciclueuler.out");

	int V,E;
	vector < edge_type > edges;
	vector < list<int> > G;


	in >> V >> E;
	G.resize(V + 1);

	int x,y;
	for(int i = 0; i < E; ++i)
	{
		in >> x >> y;
		edges.push_back(edge_type(x,y,true));
		G[x].push_back(i);
		G[y].push_back(i);
	}

	if(!isEuler(G,edges,V,E))
	{
		out << -1;
	}
	else
	{
		vector<int> tour( EulerTour(G,edges,V,E) );

		for(vector<int>::iterator i = tour.begin(); i != tour.end(); ++i)
		{
			out << *i << " ";
		}
	}

	return 0;
}