Cod sursa(job #881875)

Utilizator andrei.baliciBalici Andrei andrei.balici Data 18 februarie 2013 18:41:36
Problema Ciclu Eulerian Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.7 kb
#include <cstdio>
using namespace std;
FILE * intrare = fopen("ciclueuler.in","r");
FILE * iesire = fopen("ciclueuler.out","w");

//prin liste de adiacenta alocate dinamic: se modifica citirea, modificarea cautarii vecinului, eliminarea unei muchii (stergem efectiv pe x din y si pe y din x sau nu stergem nimic, doar invalidez logic)

int n, m;
int d[10000], viz[10000];
int G[10000][10000];

struct NOD{int vf; struct NOD * urm;};
typedef struct NOD * LISTA;

LISTA C1, C2, sfC1, sfC2;

int ciclu(int x, LISTA& C, LISTA& sfC);
bool conex();
void citire();
void dfs(int x);
int gradepare();
void afisare();
void determina_eulerian();

int main()
	{
	citire();
	if ( conex() && gradepare() )
		{
		determina_eulerian();
		afisare();
		}
	else
		fprintf(iesire,"-1\n");
	return 0;
	}

void afisare()
	{
	LISTA p;
	for (p=C1;p->urm!=NULL;p=p->urm)
		fprintf(iesire,"%d ", p->vf);
	fprintf(iesire,"\n");
	}

bool conex()
	{
	int i, x;
	//caut un varf neizolat
	for (x=1;x<=n&&!d[x];x++);
	if (x>n) return 1;
	//x este varf neizolat
	dfs(x);
	for (i=1;i<=n;i++)//verific daca au mai ramas varfuri nevizitate si neizolate
		if (!viz[i]&&d[i])return 0;
	return 1;
	}

void dfs(int x)
	{
	int i;
	viz[x]=1;
	for (i=1;i<=n;i++)
		if(G[x][i] && viz[i]==0)
			dfs(i);
	}

int gradepare()
	{
	int i;
	for (i=1;i<=n;i++)
		if (d[i]%2==1)return 0;
	return 1;
	}

void citire()
	{
	int i, x, y;
	fscanf(intrare,"%d%d", &n, &m);
	for (i=1;i<=m;i++)
		{fscanf(intrare,"%d%d", &x, &y);
		G[x][y]++;
		G[y][x]++;
		d[x]++;
		d[y]++;}
	}

void determina_eulerian()
	{
	int x, nr2, total;
	LISTA p, q;
	//caut un varf cu gradul nenul
	for (x=1;x<=n&&!d[x];x++);
	//x are gradul nenul
	total=ciclu (x, C1, sfC1);
	while (total<m)
		{
		//caut pe C1 un varf cu gradul nenul
		for (p=C1;!d[p->vf];p=p->urm);
		//acum p indica un varf cu grad nenul
		nr2=ciclu(p->vf, C2, sfC2);
		//reunesc ciclul C1 cu ciclul C2
		q=p->urm;
		p->urm=C2->urm;
		sfC2->urm=q;
		total+=nr2;
		}
	}

int ciclu(int x, LISTA& C, LISTA& sfC)
	{
	int y, uvf, lg=0;
	LISTA p;
	//incep ciclul cu varful x
	//aloc memorie pt un nod
	p=new NOD;
	p->vf=x;
	p->urm=NULL;
	C=sfC=p;//este este singurul nod din lista
	do
		{
		//caut y un varf adiacent cu ultimul varf din lista
		uvf=sfC->vf;
		//parcurg linia de adiacenta uvf pana dau de un y adiacent cu el
		for (y=1;!G[uvf][y] && y<=n;y++);
		//adaug muchia uvf, y in ciclul eulerian
		//aloc memorie pentru un nou varf
		p=new NOD;
		p->vf=y;
		p->urm=NULL;
		sfC->urm=p;
		sfC=p;
		lg++;
		//am folosit aceasta muchie; o elimin din graf
		G[uvf][y]--;G[y][uvf]--;
		d[y]--;d[uvf]--;
		}
	while (y!=x);
	return lg;
	}