我的目标是生成一个由 n 个顶点组成的有向图,使得每个顶点都有一条出边和一条入边。我认为实现此目的的一种方法是将所有顶点放入一个罐中,并让顶点轮流洗牌并拉出条目——例如,如果顶点 1 拉出顶点 3,则意味着将有一条从 1 到 3 的边。如果一个顶点将自己从罐中拉出,它只是将其放回并重新洗牌。如果最后,最后一个顶点发现罐子只包含它自己,那么我们需要重新开始。这是我的 Kotlin 代码:
fun generateGraph(n: Int): Map<Int, Int> {
val vertices : List<Int> = (1..n).toList()
while (true) {
val pot = vertices.toMutableList()
val result = mutableMapOf<Int, Int>()
for (vertex in 1 until n) {
do {
java.util.Collections.shuffle(pot)
} while (pot[0] == vertex)
result.put(vertex, pot.removeAt(0))
}
if (pot[0] != n) {
result.put(n, pot.removeAt(0))
return result
}
else {
// The last vertex left in the pot is also the last one unassigned. Try again...
}
}
}
似乎有效。然而,在测试时,我发现它显示的一些图表比其他图表多。当 n 为 3 时,唯一有效的图是循环
{1=3, 2=1, 3=2}
{1=2, 2=3, 3=1}
但我发现第一个出现的次数是第二个的两倍:
fun main(args: Array<String>) {
val n = 3
val patternCounts = mutableMapOf<Map<Int, Int>, Int>()
val trials = 10000
(1..trials).forEach({
val graph = generateGraph(n)
patternCounts[graph] = patternCounts.getOrDefault(graph, 0) + 1
})
println(patternCounts)
}
刚刚打印的这一系列
{{1=3, 2=1, 3=2}=6669, {1=2, 2=3, 3=1}=3331}
我缺少什么?还有,有没有办法让这件事变得公平?