Cod sursa(job #2819821)

Utilizator DianaZaharia132nr2Zaharia Diana Cristiana DianaZaharia132nr2 Data 19 decembrie 2021 10:06:30
Problema Ciclu Eulerian Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.04 kb
#include <iostream>
#include<fstream>
#include<vector>
#include<stack>

using namespace std;
ifstream f("ciclueuler.in");
ofstream g("ciclueuler.out");

vector<pair<int,int>> v[100005];
stack<int> s;

int grd[100005];
bool ok[100005], done[500025];//ok pt proprietatea de vizitat pt parcurgerea in adancime,
                              //done pt "stergerea" muchiilor pt eulerian
int N,M;

void dfs(int a)
{
    ok[a]=true;
    for(auto x: v[a])
    {
        if(ok[x.first]==false)
            dfs(x.first);
    }
}

//marcam nodul ca vizitat
// parcurgem vecinii nodului curent, daca acestia nu au fost vizitati,
//pornim un alt algoritm DFS, ne intoarcem de unde am plecat folosind recursivitatea

void euler(int a)
{
   while(v[a].size()>0)//mai sunt muchii cu varful a
    {
        while(v[a].size()>0 and done[v[a].back().second]==true) //am trecut prin vecin scoatem muchia
            v[a].pop_back();

        if(v[a].size()>0)//inca muchii cu varful a
        {
            int urm=v[a].back().first, nr=v[a].back().second; //urm varf (back () pt ultimul element din vector)
            done[nr]=true;//marcam indicele muchiei ca parcurs ca sa marcam ca muchia a fost parcursa
            v[a].pop_back();//scoatem muchia
            euler(urm);//facem recursiv pt urmatorul
        }
    }
    s.push(a);

}

/*adăugăm pe stivă un vârf oarecare – de exemplu 1;
cât timp stiva nu este vidă
fie a – nodul din vârful stivei
determinăm nodurile x adiacente cu a.(icepem de la ultimul memorat in vector).Eliminăm muchia [a,x]  și adăugăm nodul x pe stivă (apel recursiv)
continuăm cu nodul situat în vârful stivei
adăugăm nodul a în stiva, stiva construită reprezintă un ciclu eulerian*/
int main()
{

    f>>N>>M;
    //cin>>N>>M;
    int x, y,nr=0;
    for(int i=1;i<=M;i++)
    {
        nr++;
        f>>x>>y;
        //cin>>x>>y;
        v[x].push_back({y,nr});
        v[y].push_back({x,nr});
        grd[x]++;//gradul lui x
        grd[y]++;//gradul lui y
    }

 //for(auto x: v[1])
// cout<<x.first<<x.second;
//exemplu pt 4 4 1 2 1 3 2 4 3 4
// memoreaza v[1]= 2132 v[2]=1143 etc..

    for(int i=1;i<=N;i++)
        {
        if(grd[i]%2==1)
        {
            g<<-1;
            f.close();
            g.close();
            return 0;
        }
    }
     //verficam eulerian, toate gradele trb sa fie pare,daca nu sunt pare atunci iesim din main prin return 0,gata

    dfs(1); //parcurgere dfs

    for(int i=1;i<=N;i++)
    {
        if(ok[i]==false)
        {
            g<<-1;
            f.close();
            g.close();
            return 0;
        }
    }
    //verificam ciclu eularian daca viziteaza toate muchiile din E,
    //altfel nu e ciclu eulerian iesim din main prin return 0,gata

    euler(1); //stim ca e eulerian, cautam un ciclu si il tinem in stiva
    //afisam ciclul din stiva

    while(!s.empty())
    {
      if(s.size()>=2)
         g<<s.top()<<' ';
        s.pop();
    }
f.close();
g.close();
    return 0;
}