Description
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的
最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生
成树可能很多,所以你只需要输出方案数对31011的模就可以了。 Input第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整
数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,0
00。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。 Output输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。
首先需要一个结论,对于一个图的不同最小生成树,每种方案所包含的每种权值的边的数量一定一致。换句话说,把每种方案包含的所有边的边权都写下来,写出来的序列一定都一样。关于这个结论的说明放在最后。
这样的话,可以先做一遍kruskal,记下每种边权的使用次数,然后对于每种边权进行dfs,判断有多少种合法的组合方式【一种方案合法意味着:1.加入每条边时,边的两端点一定属于不同的并查集,也就是仍然要符合kruskal的要求。2.加入的总边数等于开始统计的使用次数。第一条要求也就决定了不能用组合数进行计算,只能dfs,而因为相同边权的边不超过10,再加上一些最简单的剪枝,运行速度很快。】,然后用乘法原理即可。
注意:
1.dfs的时候要回溯,所以这里的并查集不能进行路径压缩。
2.处理完每种边之后要把这些边加上去,这才是kruskal的过程。
3.考虑图不连通,即不存在最小生成树的情况。
最后说一下原理。考虑kruskal的过程,只有当这一权值的边全部考虑之后才会考虑权值比他大的边。举个最简单的例子,假设有两种方案,第一种方案有边x1,x4,第二种有边x2,x3,且x1< x2< x3< x4。因为一条边只能连接两个连通块,那么x2,x3中一定有一个