Cod sursa(job #881986)

Utilizator MonicaVizitiuMonica Vizitiu MonicaVizitiu Data 18 februarie 2013 20:06:48
Problema Ciclu Eulerian Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 2.94 kb
#include<fstream>
#define NMAX 1000
#include<vector>
using namespace std;

ifstream fin("ciclueuler.in");
ofstream fout("ciclueuler.out");

struct NOD
{
	int inf;
	struct NOD* urm;
};
typedef struct NOD* Lista;

int d[NMAX];
bool viz[NMAX];
int n, m, k;
vector<int>a[NMAX];

Lista C1, C2, sfC1, sfC2;

void citire();
void rez();
void dfs(int x);
void det_eulerian();
bool conex();
int gradepare();
int ciclu(int x, Lista &C, Lista &sfC);
void afisare();

int main()
{
    citire();
    if(conex()&&gradepare())
    {
       //fout<<"Graful este eulerian!"<<'\n';
       det_eulerian();
       afisare();
    }
    else
        fout<<-1<<'\n';
    return 0;
}

void citire()
{
    int i, x, y;
    fin>>n>>m;
    for(i=1;i<=m;i++)
    {
        fin>>x>>y;
        d[x]++; d[y]++;
        a[x].push_back(y); a[y].push_back(x);
    }
}


bool conex()
{
    int i;
    //caut un vf neizolat
    for(i=1;i<=n&&!d[i];i++);
        if(i>n) return 1;
    dfs(i);
    //i este vf neizolat
    for(i=1;i<=n;i++)
        if(!viz[i]&&d[i])
            return 0;
    return 1;
}

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

void dfs(int x)
{
    int i;
    viz[x]=true;
    for(i=0;i<a[x].size();i++)
        if(!viz[a[x][i]])
            dfs(a[x][i]);
}

void det_eulerian()
{
    int x, nr2, total;
    Lista p, q;
    //caut un varf cu gradul nenul
    for(x=1;x<=n&&!d[x];x++);
    //x are gradu nenul
    total=ciclu(x, C1, sfC1);
    while(total<m)
    {
        //caut pe C1 un vf cu gradul nenul
        for(p=C1;!d[p->inf];p=p->urm);
        //acum p indica un vf cu grad nenul
        nr2=ciclu(p->inf, 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, i;
	Lista p;
	//incep ciclul cu vf x
	p=new NOD; p->inf=x; p->urm=NULL;
    C=sfC=p;//initial x este primul si ultimul nod din ciclu
    do
    {
        //caut y un vf adiacent cu ultimul vf din lista
        uvf=sfC->inf;
        //parcurg linia uvf pana dau de un y adiacent cu el
        for(i=0;!a[uvf][i]&&i<a[uvf].size();i++);
        y=a[uvf][i];
        //adaug muchia [uvf,y] in ciclul eulerian
        p=new NOD; p->inf=y; p->urm=NULL;
        //il adaug la sfarsitul ciclului
        sfC->urm=p; sfC=p;
        lg++;
        //am folosit aceasta muchie, o elimin din graf
        a[uvf][i]=0; //elimin muchia
        for(i=0;i<a[y].size();i++)
            if(a[y][i]==uvf)
            {
                a[y][i]=0; break;
            }
        d[y]--; d[uvf]--;//scad gradele
    }
    while(y!=x);//cat timp n-am ajuns din nou la nodul innitial, adica nu am format un ciclu
    return lg;
}

void afisare()
{
    Lista p;
    for(p=C1; p; p=p->urm)
        fout<<p->inf<<' ';
    fout.close();
}