Cod sursa(job #882249)

Utilizator manuelahordunaHorduna Manuela manuelahorduna Data 18 februarie 2013 22:57:59
Problema Ciclu Eulerian Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 5.75 kb
#include<fstream>
#define NMAX 10005
using namespace std;
ifstream fin ("ciclueuler.in");
ofstream fout ("ciclueuler.out");

struct nod{int vf;struct nod *urm;};
typedef struct nod * Lista;
Lista C1, C2, sfC1, sfC2;

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

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

int main()
{
    citire();
    if(conex() && gradepare())
    {
        determina_ciclu();
        afisare();
    }
    else
        fout<<"-1"<<'\n';
    fout.close();
    return 0;
}

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

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

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

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

void determina_ciclu()
{
    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 ciclu C1 cu ciclul C2
        q=p->urm; p->urm=C2->urm; sfC2->urm=q;
        total+=nr2;
    }
}

int ciclu(int x, Lista& C, Lista& sfC)
{
    Lista p;
    int y, lg=0, i, j, uvf;//ultimul vf din lista
    //incep ciclu cu vf x
    //aloc memorie pt un nod
    p=new nod;
    p->vf=x; p->urm=NULL;
    C=sfC=p;// el este primul, ultimul, singurul nod din lista
    do
    {
        //caut y, un vf adiacent cu ultimul varf din lista
        uvf=sfC->vf;
        //parcurg lista de adiacenta a lui uvf si iau primul nod dif de 0
        for(i=1; i<=G[uvf][0];i++)
            if( G[uvf][i]!=0)
                break;
        y=G[uvf][i];
        //adaug muchia [uvf,y] in ciclu eulerian
        //aloc memorie
        p=new nod;
        p->vf=y; p->urm=NULL;
        //il adaug la sfarsitul ciclului
        sfC->urm=p; sfC=p;
        lg++;
        //am folosit aceasta muchie, o elimin din graf
        G[uvf][i]=0;
        for(j=1;j<=G[y][0];j++)//ne plimbam in lista si il cautam pe uvf
            if(G[y][j]==uvf)
            {
                G[y][j]=0; break;//marcam cu 0 pt a nu mai fi folosit
            }
        d[uvf]--; d[y]--;
    }
    while(y!=x);
    return lg;
}

void afisare()
{
    Lista p;
    for(p=C1; p;p=p->urm)
        fout<<p->vf<<' ';
    fout<<'\n';
}
/*#include <fstream>
#define dmax 10002
using namespace std;
ifstream fin("ciclueuler.in");
ofstream fout("ciclueuler.out");

struct nod {int vf; struct nod *urm;};
typedef struct nod* Lista;
Lista C1, C2, sfC1, sfC2;

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

int n,m;
int viz[dmax];
int d[dmax];
bool g[dmax][dmax];

int main()
{
    citire();
    if(conex() && gradepare())
        {//fout<<"eulerian"<<'\n';
        determina_eulerian();
        afisare_ciclu();}
    else
        //fout<<"neulerian"<<'\n';
        fout<<"-1"<<'\n';
    fout.close();
    return 0;
}

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

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

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

void citire()
{
    int i,x,y;
    fin>>n>>m;
    for(i=0;i<m;i++)
        {
            fin>>x>>y;
            d[x]++;
            d[y]++;
            g[x][y]=g[y][x]=true;
        }
}

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

int ciclu(int x, Lista& C, Lista& sfC)
{
    Lista p;
    int y,uvf,lg=0;
    //incep ciclul cu vf x
    //aloc memorie pt un nod
    p=new nod;
    p->vf=x;
    p->urm=NULL;
    C=sfC=p;//este singurul
    do
    {
        //caut y un vf adiacent cu ultimul vf din lista
        uvf=sfC->vf;
        //parcurg linia uvf pana dau de un y adiacent cu el
        for(y=1; !g[uvf][y];y++);
        //adaug muchia aceasta [uvf, y] in ciclul eulerian
        //aloc memorie pt un nou vf
        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]=false;
        d[y]--;
        d[uvf]--;
    }
    while(y!=x);
    return lg;
}

void afisare_ciclu()
{
    Lista p;
    for(p=C1;p;p=p->urm)
        fout<<p->vf<<' ';
    fout<<'\n';
}*/