众所周知,给定n个点m条边的有向图,这里认为点从0到n-1标号,如果采用邻接链表的方式存储,也就是对每个点u拉出一条链表来记录所有满足存在u->v的有向边的点v,那么总共需要m个链表节点(让我们忘掉头结点的悲伤)。
(该图引自"Introduction to Algorithms, 3rd Edition")
小Q同学偶然间得知了一种压缩算法,可以有效的减少链表节点个数,具体来说,就是每个链表节点记录一个二元组(offset,bitmask),这里bitmask是一个w位无符号整数,通常来说w=32或者64,并且offset是w的非负整数倍,那么如果点u拉出的链表中某个节点的bitmask的第k位是1,则说明存在u -> offset+k的有向边。
但是这个算法在某些情况下并不能很有效的压缩原图,比如存在点0到点1,w+1,2w+1,3w+1,...的有向边时,从点0拉出的链表节点个数并没有减少。为了应对这种情况,一个解决办法是对原图重标号,也就是构造一个0,1,2,...,n-1的排列p,使得原图的点i对应新图中的点p_i,然后再对新图进行压缩。
小Q同学想知道有多少种重标号的方案能够最小化存储压缩后的图所需要的链表节点个数,由于这个问题在w ≥ 3的情况下相当困难,你只需要帮小Q同学解决w=2的情况即可。