Confesso che nemmeno io l'ho compreso appieno, però inizio a racappezzarmi.
Dunque (leggendo da destra a sinistra):

const int* p significa: p è un puntatore a un int costante, quindi si può cambiare dove punta p ma non il valore della variabile a cui punta.
codice:
int i=10;
int j = 1000;
const int* p = &i;
*p = 20; // illegale
p = &j; // ok
int* const p significa: p è puntatore costante a un int, quindi non si può cambiare dove punta p ma si può cambiare il valore della variabile a cui punta.
codice:
int i=10;
int j = 1000;
int* const p = &i;
*p = 20; // ok
p = &j; // illegale
const int* const p significa: p è puntatore costante a un int costante, quindi non si può cambiare dove punta p, ne si può cambiare il valore della variabile a cui punta.
codice:
int i=10;
int j = 1000;
const int* const p = &i;
*p = 20; // ok
p = &j; // illegale
Alla luce di questo, mi sono accorto che la & finale di const int* const& p non serve a niente.

Il compilatore poi non può permette l'assegnazione a un int* di un const int* const per cui serve il const_cast appunto.
Fosse stato un oggetto e non un puntatore non c'erano problemi, visto che viene fatta una copia dell'oggetto e non assegnato un indirizzo.

Sostituisci int* con Nodo* (o Nodo<T>* dove serve) e sei a posto.

Per quanto riguarda il resto.
Non ho trovato spiegazioni sul perché const int*& p non compili.
Penso comunque dipenda dal fatto che, metaforicamente, uno voglia girare a destra, l'altro a sinistra e alla fine vadano a sbattere dritti contro il compilatore.