给定有向无环图中所有边,计算图的拓扑排序解的个数。
第一行为用例个数,后面每一行表示一个图中的所有边,边的起点和终点用空格隔开,边之间使用逗号隔开。
拓扑排序解的个数。
1
a c,b c,c d,d e,d f,e g,f g
4
因为算法课需要,所以只好将别人代码进行翻译,暂时还没看懂原理。
代码基本来自对【ZJU 1346 Comparing Your Heroes 状态压缩DP 拓扑排序的计数】的翻译,因为网上对拓扑排序计数的资料太少,所以我暂时用python进行了改写。
需要对size进行修改,因为不知道输入判例会有多少种字母,size=26的话会TLE,size太小的话会RE,经过我的测试,size=13时,size最小且能AC,说明测试用例的字母种数为13。
def inputPre():
global name, pre, m, n
for i in range(m):
v = 0
u = 0
while u < n:
if p[i][0] == name[u]:
break
else:
u += 1
if u == n:
name.append(p[i][0])
n += 1
while v < n:
if p[i][1] == name[v]:
break
else:
v += 1
if v == n:
name.append(p[i][1])
n += 1
pre[v] |= (1 << u)
def solve():
global dp, n
dp[0] = 1
for s in range(1 << n):
if dp[s] != 0:
for i in range(n):
if ((s & pre[i]) == pre[i]) and not (s & (1 << i)):
dp[s | (1 << i)] += dp[s]
print(dp[(1 << n) - 1])
if __name__ == '__main__':
N = int(input())
for k in range(N):
pairs = list(map(str, input().split(","))) # 起点终点对集合
m = len(pairs)
n = 0
p = [] # 存储起点终点对
for i in range(m):
pair = pairs[i].split()
p.append(pair)
name = []
size = 13
pre = [0 for i in range(size)]
dp = [0 for i in range(1 << size)]
inputPre()
solve()