ishamilt.cpp

/* COMIENZO DE DESCRIPCION

   __USE_WIKI__
   Dado un grafo #map<int, set<int> >G#
   y una lista de vertices #list<int> L# determinar si #L# es un
   _camino hamiltoniano_ en #G#. 
   [Tomado en tercer parcial 2011-11-24].
   keywords: conjunto, grafo

  FIN DE DESCRIPCION */
// -------------------------------------------------------------------

#include <cstdio>
#include <cassert>

#include <list>
#include <map>
#include <set>
#include <string>

using namespace std;

typedef map<int, set<int> > graph_t;
//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// `cycle=1' indica si chequea para un ciclo
// Hamiltoniano, si `cycle=0' chequear para un camino
// Hamiltoniano
bool is_hamilt_path(graph_t &G,list<int> &L,int cycle=0) {
  // chequea que todos los indices en L
  // sean relamente nodos del grafo (o sea claves del map)
  list<int>::iterator x=L.begin();
  while (x!=L.end()) 
    if (G.find(*x++)==G.end()) 
      return false;

  // Guarda los vertices que ya fueron visitados
  set<int> visited;
  // x,y son dos posiciones consecutivas en la lista
  x = L.begin();
  list<int>::iterator start=x, y, last;
  // Si la lista esta vacia la unica posibilidad
  // para que sea Hamiltoniano es que el grafo este vacio
  if (x==L.end()) return G.empty();
  // Chequea si el vertice esta en el grafo o no
  if (G.find(*x)==G.end()) return false;
  while (1) {
    // Si ya fue visitado NO es Ham
    if (visited.find(*x)!=visited.end()) return false;
    visited.insert(*x);
    // apunta con y al siguiente de x
    y = x; y++;
    if (y==L.end()) break;
    // Si y no esta en el gradfo no es Ham
    if (G.find(*y)==G.end()) return false;
    // Toma los vecinos de x 
    set<int> &xngbrs = G[*x];
    // Si y no es adyacente a x NO es Ham
    if (xngbrs.find(*y)==xngbrs.end()) return false;
    x=y;
  }
  // Chequea que los haya visitado a todos, para eso
  // solo basta con chequear que los tamanos sean iguales
  if (!cycle) return L.size()==G.size();
  // Para detectar ciclos Hamiltonianos hay que chequear
  // ademas que el ultimo este conectado con el primero
  if (L.size()!=G.size()) return false;
  last = x;
  set<int> &ngbrs = G[*last];
  return ngbrs.find(*start)!=ngbrs.end();
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
bool is_hamilt_cycle(graph_t &G,list<int> &L) {
  return is_hamilt_path(G,L,1);
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int modulo(int n,int m) {
  int r = n%m;
  if (r<0) r+= m;
  return r;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int main() {
  // simple 1D graph
  int N=12;
  graph_t G;
  for (int j=0; j<N; j++) {
    set<int> &ngbrs = G[j];
    ngbrs.insert(modulo(j+1,N));
    ngbrs.insert(modulo(j-1,N));
  }

  list<int> L;
  // for (int j=0; j<N-1; j+=2) L.push_back(j);
  for (int j=0; j<N; j++) L.push_back(modulo(6+j,N));
  
  printf("is Hamilt path? %d\n",is_hamilt_path(G,L));
  printf("is Hamilt cycle? %d\n",is_hamilt_cycle(G,L));
  return 0;
}

Generated by GNU Enscript 1.6.6.