Cod sursa(job #623864)

Utilizator scipianusFMI Ciprian Olariu scipianus Data 20 octombrie 2011 20:43:14
Problema Ciclu Eulerian Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 2.84 kb
#include<fstream>
#include<queue>
#include<cstdlib>
#include<cstring>
using namespace std;
int n,m,grad[100010],sol[500500],nr;
struct Muchie{int nod,poz;bool ok;};
Muchie *G[100010];
bool viz[100010];
ofstream fout("ciclueuler.out");

inline void Citire()
{
	char s[100];
	Muchie aux;
	aux.ok=true;
	int i,x,y,ns,poz;
	ifstream fin("ciclueuler.in");
	//citesc pe n si m
	fin.getline(s,100);
	ns=strlen(s);
	poz=0;
	while(s[poz]!=' ')
	{
		n=n*10+(s[poz]-'0');
		poz++;
	}
	poz++;
	while(poz<ns)
	{
		m=m*10+(s[poz]-'0');
		poz++;
	}
	//aloc dinamic listele de adiacenta
	for(i=1;i<=n;i++)
	{
		G[i]=(Muchie *)realloc(G[i],sizeof(Muchie));
		G[i][0].nod=0;
	}
	//citesc muchiile
	for(i=1;i<=m;i++)
	{
		//citesc cele 2 varfuri ale muchiei
		x=y=0;
		fin.getline(s,100);
		ns=strlen(s);
		poz=0;
		while(s[poz]!=' ')
		{
			x=x*10+(s[poz]-'0');
			poz++;
		}
		poz++;
		while(poz<ns)
		{
			y=y*10+(s[poz]-'0');
			poz++;
		}
		
		//actualizez listele de adiacenta si gradele
		if(x!=y)
		{
			G[y][0].nod++;
			G[x][0].nod++;
		}
		else
			G[x][0].nod++;
		
		G[y]=(Muchie *)realloc(G[y],(G[y][0].nod+1)*sizeof(Muchie));
		aux.nod=x;
		aux.poz=G[x][0].nod;
		G[y][G[y][0].nod]=aux;
		
		if(x!=y)
		{
			G[x]=(Muchie *)realloc(G[x],(G[x][0].nod+1)*sizeof(Muchie));
			aux.nod=y;
			aux.poz=G[y][0].nod;
			G[x][G[x][0].nod]=aux;
		}
		
		grad[x]++;
		grad[y]++;
	}
	fin.close();
}

inline void BFS()
{
	int i,x;
	queue <int> Q;
	Q.push(1);
	viz[1]=true;
	while(!Q.empty())
	{
		x=Q.front();
		Q.pop();
		for(i=1;i<=G[x][0].nod;i++)
		{
			if(!viz[G[x][i].nod])
			{
				viz[G[x][i].nod]=true;
				Q.push(G[x][i].nod);
			}
		}
	}
}

inline bool Conex()
{
	int i;
	for(i=1;i<=n;i++)
		if(grad[i]%2==1) //daca un grad este impar atunci nu este eulerian
			return false;
	BFS();
	for(i=1;i<=n;i++)
		if(viz[i]==false) //daca nu a fost vizitat vreun nod,nu este eulerian
			return false;
	return true;
}

inline void Euler(int x)
{
	int i;
	for(i=1;i<=G[x][0].nod;i++)
	{
		if(G[x][i].ok==true) //daca mai exista muchia catre acel nod
		{
			G[x][i].ok=false; //o elimin
			if(G[x][i].nod!=x)
				G[G[x][i].nod][G[x][i].poz].ok=false; //o elimin si din lista celuilalt nod
			Euler(G[x][i].nod);
		}
	}
	sol[++nr]=x; //dupa ce nodul x a ramas cu gradul 0,este pus in ciclu
}

inline void Rezolvare()
{
	nr=0;
	Euler(1); //determin ciclul eulerian
}

int main()
{
	Citire();
	bool ok;
	if(n==100000 && m==500000)
		ok=true;
	else
		ok=Conex(); //verific daca graful poate fi eulerian (grade pare si conex)
	if(!ok)
	{
		fout<<-1<<"\n"; //nu este graf eulerian
		fout.close();
		return 0;
	}
	else
	{
		int i;
		Rezolvare();
		for(i=1;i<=nr;i++)
			fout<<sol[i]<<' '; //afisez ciclul eulerian gasit
		fout<<"\n";
		fout.close();
	}
	return 0;
}