Cod sursa(job #2930992)

Utilizator Remus.RughinisRemus Rughinis Remus.Rughinis Data 30 octombrie 2022 00:31:05
Problema Ciclu Eulerian Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.74 kb
#include <fstream>
#include <iostream>
#include <vector>
#define MAXM 500000
#define MAXN 100000

using namespace std;

class Edge {
public:
  int a;
  int b;
  bool marked = false;

  Edge(int x, int y) {
    a = x;
    b = y;
  }
};

vector<vector<int>> v;
vector<Edge> edges;
int selfConnected[MAXN];
int marked[MAXN], mki;
int r[MAXM], ri, noEdges[MAXN], n, m;

void resetMarked() {
  mki++;

  //   for (int i = 0; i < n; i++) {
  //     marked[i] = false;
  //   }
}

int dfs(int id) {
  if (marked[id] == mki)
    return 0;

  int s = 1, i;
  marked[id] = mki;

  for (i = 0; i < v[id].size(); i++) {
    Edge next = edges[v[id][i]];

    if (!next.marked) {
      if (next.a == id)
        s += dfs(next.b);
      else
        s += dfs(next.a);
    }
  }

  return s;
}

bool checkEdge(Edge *edge, int origin) {
  // printf("Check: %d %d  %d\n", edge->a + 1, edge->b + 1, edge->marked);
  if (edge->marked == true)
    return false;

  if (noEdges[origin] == 1)
    return true;

  int x, y;
  x = dfs(origin);
  resetMarked();

  edge->marked = true;
  y = dfs(origin);
  resetMarked();
  edge->marked = false;

  if (x == y)
    return true;
  return false;
}

void getEuler(int id) {
  int i;
  // printf("%d\n", id + 1);
  r[ri] = id;
  ri++;

  for (i = 0; i < v[id].size(); i++) {
    Edge *next = &edges[v[id][i]];

    if (checkEdge(next, id)) {
      next->marked = true;
      noEdges[next->a]--;
      noEdges[next->b]--;

      //  for (i = 0; i < n; i++)
      //    printf("%d ", noEdges[i]);
      //  printf("\n");

      if (next->a == id)
        getEuler(next->b);
      else
        getEuler(next->a);
      return;
    }
  }
}

int findStart() {
  int i;

  for (i = 0; i < n; i++)
    if (v[i].size() % 2 != 0)
      return i;

  i = 0;
  while (v[i].size() == 0)
    i++;

  return i;
}

int main() {
  int i, a, b;

  ifstream fin("ciclueuler.in");
  fin >> n >> m;

  v.resize(n);

  for (i = 0; i < m; i++) {
    fin >> a >> b;
    a--;
    b--;

    if (a == b)
      selfConnected[a]++;

    else {
      edges.push_back(Edge(a, b));

      v[a].push_back(edges.size() - 1);
      v[b].push_back(edges.size() - 1);

      noEdges[a]++;
      noEdges[b]++;
    }
  }
  fin.close();

  //  for (i = 0; i < n; i++)
  //    printf("%d ", noEdges[i]);
  //  printf("\n");

  // Gasim de unde sa incepem
  ri = 0;
  mki = 1;
  getEuler(findStart());
  // printf("\n%d\n", noEdges);

  // Verificam daca am trecut prin toate nodurile cu muchii
  ofstream fout("ciclueuler.out");
  if (edges.size() != ri - 1)
    fout << -1 << endl;
  else {
    for (i = 0; i < ri - 1; i++) {
      while (selfConnected[r[i]] > 0) {
        fout << r[i] + 1 << " ";
        selfConnected[r[i]]--;
      }
      fout << r[i] + 1 << " ";
    }
    fout << endl;
  }
  fout.close();

  return 0;
}