viernes, 3 de junio de 2011

Longest path in a tree

 You are given an unweighted, undirected tree. Write a program to output the length of the longest path (from one node to another) in that tree. The length of a path in this case is number of edges we traverse from source to destination.
Input

The first line of the input file contains one integer N --- number of nodes in the tree (0 < N <= 10000). Next N-1 lines contain N-1 edges of that tree --- Each line contains a pair (u, v) means there is an edge between node u and node v (1 <= u,v <= N).
Output

Print the length of the longest path on one line. 


Example
Input:
3
1 2
2 3

Output:
2


https://www.spoj.pl/problems/PT07Z/



public class LongestPathInATree 
{
   Lista[] vertices;
 
   public static void main( String args[] ) throws Exception
   {
      new LongestPathInATree().resolver();
      }
 
   public LongestPathInATree()
   {
      // Vector de listas, donde se almacenaran las aristas
      // para cada vertice
      vertices = new Lista[ 10001 ];
  
      for( int i = 1; i < vertices.length; i ++ )
      vertices[ i ] = new Lista();
   }
 
   public  void resolver(  ) throws Exception
   {
  
      int numNodos = sig();
      int orig, dest;
  
      /**
      * Representaremos el arbol como un vector de listas enlazadas,
      * algo similar a como se representan los grafos en memoria.
      */
      for( int i = 1; i < numNodos; i ++ )
      {
         orig = sig();
         dest = sig();
   
         // Como las aristas son sin direccion, tenemos que anadir
         // 2 veces cada arista
         vertices[ orig ].anadir( dest );
         vertices[ dest ].anadir( orig );
      }
  
      Nodo act = vertices[ 1 ].cab.siguiente;
      int nivelSubArbol1 = 0, nivelSubArbol2 = 0;
      int temp;
  
      /*
      * Como el arbol es libre, podemos tomar como raiz cualquier vertice,
      * en nuestro caso tomamos como raiz el vertice 1.
      * 
      * La longitud maxima entre 2 nodos del arbol, es equivalente a 
      * la suma de los 2 mayores niveles de los subarboles de la raiz 1.
      * 
      * Donde el nivel de un arbol, es igual a la longitud del camino mas
      * largo entre su raiz y una de sus hojas.
      */
      for( ; act != null; act = act.siguiente )
      {
         // Hallamos el nivel de cada subarbol de la raiz 1, y almacenamos
         // los 2 mayores niveles.
         temp = nivelSubArbol( 1, act.vertice, 1 );
    
         if( temp > nivelSubArbol1 )
         {
            nivelSubArbol2 = nivelSubArbol1;
            nivelSubArbol1 = temp;
         }
         else if( temp > nivelSubArbol2 )
         {
            nivelSubArbol2 = temp;
         }
      }
  
      System.out.println( nivelSubArbol1 + nivelSubArbol2 );
   }
 
   public int nivelSubArbol(  int padre, int vertice, int longCamino )
   {
      Nodo hijo = vertices[ vertice ].cab.siguiente;
  
      // Si solo existe un hijo, eso indica que solo hay una arista, 
      // que es la que lo une con su padre, esta no se debe procesar.
      if( hijo.siguiente == null )
         return longCamino;
  
      int nivelMaximoSubArbol = 0, temp;
  
      // Calculamos el nivel para cada subarbol del nodo actual,
      for(  ; hijo != null; hijo = hijo.siguiente )
      {
         // Verificamos que no estemos procesando al padre el vertice
         if( hijo.vertice != padre )
         {
            // Calculamos el nivel maximo de este subarbol, aplicando
            // recursivamente el mismo procesidiento para cada uno
            // de sus subarboles
            temp = nivelSubArbol( vertice, hijo.vertice, longCamino + 1 );
    
            if( temp > nivelMaximoSubArbol )
               nivelMaximoSubArbol = temp;
         }
      }
  
      return nivelMaximoSubArbol;
   }
 
   class Nodo
   {
      int vertice;
      Nodo siguiente;
      
      Nodo( int vert )
      {
         vertice = vert;
      }
   }
 
   class Lista
   {
      Nodo ult = new Nodo( 0 );
      Nodo cab = ult;
  
      void anadir( int val )
      {
         ult.siguiente = new Nodo( val );
         ult = ult.siguiente;
      }
   }
 
   public static int sig() throws Exception
   {
      int val = 0;
      int car = System.in.read();
  
      while( car > 47 && car < 58 )
      {
         val = 10 * val + car - 48;
         car = System.in.read();
      }
  
      return val;
   }
}

1 comentario:

  1. disculpa quisiera saber más o menos por qué tu solución es correcta si tomo las maximas alturas de cada rama y sumo solo la maxima y la casi maxima, no dan ciertos casos de la pagina, creo que el problem setter ha cambiado la test data.

    ResponderEliminar