Cod sursa(job #1356369)

Utilizator cata00Catalin Francu cata00 Data 23 februarie 2015 13:28:52
Problema Ciclu Eulerian Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.69 kb
#include <assert.h>
#include <stdio.h>

#define MAX_N 100000
#define MAX_M 500000
#define NIL -1

typedef struct {
  int v, next;
  int other; // pointer la celula-pereche din lista lui v
} adjCell;

adjCell l[2 * MAX_M];  // liste de adiacență alocate static
int adj[MAX_N];        // începutul listelor de adiacență
int st[MAX_M + 1], ss; // stiva nodurilor care încă mai au vecini
int degree[MAX_N];

void addChild(int u, int v, int cell, int other) {
  l[cell].v = v;
  l[cell].other = other;
  l[cell].next = adj[u];
  adj[u] = cell;
  degree[u]++;
}

void euler(FILE *f, int u) {
  st[ss++] = u;
  while (ss) {
    u = st[ss - 1];
    while ((adj[u] != NIL) && (l[adj[u]].v == NIL)) {
      adj[u] = l[adj[u]].next;  // sărim peste muchiile folosite deja
    }
    if (adj[u] != NIL) {
      st[ss++] = l[adj[u]].v;
      l[l[adj[u]].other].v = NIL; // marcăm celula-pereche ca folosită
      adj[u] = l[adj[u]].next;
    } else {
      ss--;
      if (ss) {    // ca să nu duplicăm primul / ultimul nod
        fprintf(f, "%d ", 1 + u);
      }
    }
  }
}

int main(void) {
  int n, m, u, v;
  FILE *f = fopen("ciclueuler.in", "r");
  assert(fscanf(f, "%d%d", &n, &m) == 2);
  for (int i = 0; i < n; i++) {
    adj[i] = NIL;
  }
  for (int i = 0; i < m; i++) {
    assert(fscanf(f, "%d%d", &u, &v) == 2);
    u--;
    v--;
    addChild(u, v, 2 * i, 2 * i + 1);
    addChild(v, u, 2 * i + 1, 2 * i);
  }
  fclose(f);

  int odd = 0;
  while ((odd < n) && ((degree[odd] & 1) == 0)) {
    odd++;
  }

  f = fopen("ciclueuler.out", "w");
  if (odd < n) {
    fprintf(f, "-1\n");
  } else {
    euler(f, l[0].v); // Garantăm că începem parcurgerea dintr-un nod cu vecini
    fprintf(f, "\n");
  }
  fclose(f);
}