Cod sursa(job #689492)

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

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<vector<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(vector<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<vector<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();

		if(!G[v].empty())
		{
				int tmp = G[v].back(); //i devine invalid daca muchia e de forma (x,x)
				G[v].pop_back();
				if(edges[tmp].x == v)
				{
					vertex.push(edges[tmp].y);

					for(vector<int>::iterator j = G[edges[tmp].y].begin(); j != G[edges[tmp].y].end();)
						if(*j == tmp)
							j = G[edges[tmp].y].erase(j);
						else ++j;
				}
				else //edges[*i].y == v
				{
					vertex.push(edges[tmp].x);		
					for(vector<int>::iterator j = G[edges[tmp].x].begin(); j != G[edges[tmp].x].end();)
						if(*j == tmp)
							j = G[edges[tmp].x].erase(j);
						else ++j;
				}
		}
		else 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 < vector<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;
}