Cod sursa(job #2820069)

Utilizator Dantelogus99Gruia Gabriel Dantelogus99 Data 19 decembrie 2021 20:34:22
Problema Ciclu Eulerian Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.91 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <climits>
using namespace std;

constexpr int INF = INT_MAX;


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



struct Edge
{
    // easier, cleaner and more expandable alternative to using a tuple for Storing sourceNodes, destinationNodes, weights, capacities etc...

    int src;
    int dest;
    int cost;


    Edge ()
    {
        src = 0;
        dest = 0;
        cost = 0;
    }
    Edge(int s, int d, int c = 0)
    {
        src = s;
        dest = d;
        cost = c;
    }

    Edge getReverse()
    {
        Edge revEdge(dest, src, cost);
        return revEdge;
    }
};



class Graph
{
    // Implementation of  << UTILITARY Functions >>  for (UN)Directed, (UN)Weighted & (UN)Flowing  << Graphs >> ;

    bool isDirected;
    bool isWeighted;

    int nrNodes;
    int nrEdges;

    vector<vector<Edge>> adjacencyList;


public:

    Graph(int n = 0, int m = 0, bool d = false, bool w = false, bool f = false) : nrNodes(n), nrEdges(m), isDirected(d), isWeighted(w), isFlowing(f) {}

    void readAdjacencyList();

    void addEdge(Edge edge);

    void removeEdge(int src, int dst);

    vector<int> getEulerCycle();


private:

    void EulerianCycleDFS(int startingNode, vector<bool>& visitedEdges, vector<int>& EClist);
};



#pragma region Definitions

void Graph :: readAdjacencyList()
{
    adjacencyList.resize(nrNodes + 1);


    for (int i = 0; i < nrEdges; i++)
    {
        Edge edge;
        fin >> edge.src >> edge.dest;

        if (isWeighted)
            edge.cost = i + 1;


        addEdge(edge);
        nrEdges--;
    }
}

void Graph :: addEdge(Edge newEdge)
{
    adjacencyList[newEdge.src].push_back(newEdge);

    if(!isDirected)
        adjacencyList[newEdge.dest].push_back(newEdge.getReverse());

    nrEdges++;
}

void Graph :: removeEdge(int src, int dst)
{
    for (int i = 0; i < adjacencyList[src].size(); i++)
        if (adjacencyList[src][i].src == src && adjacencyList[src][i].dest == dst)
            adjacencyList[src].erase(adjacencyList[src].begin() + i);

    if (!isDirected)
        for (int i = 0; i < adjacencyList[dst].size(); i++)
            if (adjacencyList[dst][i].src == src && adjacencyList[dst][i].dest == dst)
                adjacencyList[dst].erase(adjacencyList[dst].begin() + i);

    nrEdges--;
}


vector<int> Graph :: getEulerCycle()
{
    vector<bool> isVisitedEdge(nrEdges + 1, false);
    vector<int> EClist;


    for (int i = 1; i <= nrNodes; i++)
    {
        if (adjacencyList[i].size() % 2)
        {
            EClist.push_back(0);
            return EClist;
        }
    }

    EulerianCycleDFS(1, isVisitedEdge, EClist);

    if (count(isVisitedEdge.begin(), isVisitedEdge.end(), true) != nrEdges)     // if the graph is not connected, an Eulerian Cycle is not possible
        EClist.push_back(0);

    return EClist;
}

void Graph :: EulerianCycleDFS(int startingNode, vector<bool>& visitedEdges, vector<int>& EClist)
{
    for(auto& edge : adjacencyList[startingNode])
        if (!visitedEdges[edge.cost])
        {
            visitedEdges[edge.cost] = true;
            EulerianCycleDFS(edge.dest, visitedEdges, EClist);
        }

    EClist.push_back(startingNode);
}

#pragma endregion




int main()
{
    int nodes, edges;
    fin >> nodes >> edges;

    Graph G(nodes, edges, false, true, false);    // G(nodes, edges, isDirected, isWeighted);

    G.readAdjacencyList();


/* ---> EULERIAN CYCLE <--- */
    
    vector<int> EClist = G.getEulerCycle();

    if (!EClist.back())
        fout << -1;
    else
    {
        EClist.pop_back();
        for (auto x : EClist)
            fout << x << " ";
    }


    fin.close();
    fout.close();

    return 0;
}