所以,我想通过图表获得一些乐趣,现在它让我发疯了。
首先,我生成一个具有给定边数的连通图。这是容易的部分,这成了我的诅咒。基本上,它按预期工作,但我得到的结果是非常奇怪的(好吧,也许他们不是,我在这里的问题)。生成图表的算法非常简单。
我有两个数组,其中一个数组填充了从n - 1
到0
的数字,另一个数组为空。
一开始我将第一个元素移动到最后一个元素移动到空元素。
然后,在循环中,我在第一个数组的最后一个元素和第二个数组的随机元素之间创建一个边,然后再次将第一个数组中的最后一个元素移动到另一个。
在完成该部分之后,我必须在顶点之间创建随机边缘,直到我得到尽可能多的边缘。这又是非常容易的。我只是在n - 1
到void generate(int n, double d) {
initMatrix(n); // <- creates an adjacency matrix n x n, filled with 0s
int *array1 = malloc(n * sizeof(int));
int *array2 = malloc(n * sizeof(int));
int j = n - 1, k = 0;
for (int i = 0; i < n; ++i) {
array1[i] = i;
array2[i] = 0;
}
shuffle(array1, 0, n); // <- Fisher-Yates shuffle
array2[k++] = array1[j--];
int edges = d * n * (n - 1) * .5;
if (edges % 2) {
++edges;
}
while (j >= 0) {
int r = rand() % k;
createEdge(array1[j], array2[r]);
array2[k++] = array1[j--];
--edges;
}
free(array1);
free(array2);
while (edges) {
int a = rand() % n;
int b = rand() % n;
if (a == b || checkEdge(a, b)) {
continue;
}
createEdge(a, b);
--edges;
}
}
范围内随机输入两个数字,如果这些顶点之间没有边,我创建一个。
这是代码:
set serveroutput ON
DECLARE
datos RAW(100);
BEGIN
datos := utl_raw.Cast_to_raw('test');
dbms_output.Put_line('The raw variable has a lenght of '
||utl_raw.Length(datos));
END;
/
现在,如果我打印出来,它就是一张很好的图表。然后我想找一个哈密顿循环。这部分有效。然后我到了我的祸根 - 欧拉循环。问题是什么?
好吧,首先我检查所有顶点是否均匀。他们不是。总是。每一次,除非我选择生成完整的图表。
我现在感觉被自己的代码破坏了。有什么不对吗?或者它应该是这样的?我知道欧拉电路很少见,但并不罕见。请帮忙。
答案 0 :(得分:3)
让我们分析一下euleran循环的概率,为简单起见,让我们对所有带n
个顶点的图进行分析,无论边数是多少。
给定大小为n
的图G,选择一个任意顶点。它度数均匀的概率大致为1/2
(假设每个u1,u2
,P((v,u1) exists) = P((v,u2) exists)
)。
现在,从v
移除G
,并创建一个包含G'
个顶点的新图n-1
,并且所有边都没有连接到v
。
同样,对于v'
中的任意顶点G'
- 如果(v,v')
是G'
上的边缘,我们需要d(v')
为奇数。否则,我们需要d(v')
为均匀(均在G'
中)。无论哪种方式,它的概率仍大致为~1/2
。 (独立于先前的v
程度)。
...
对于i
轮次,让#(v)
为丢弃的边数,直到达到连接到v
的当前图表为止。如果#(v)
为奇数,则其当前程度为奇数的概率为~1/2
,如果#(v)
为偶数,则其当前程度为偶数的概率也为~1/2
,我们保持当前概率~1/2
我们现在可以理解它是如何工作的,并为图形为欧拉循环的概率制定一个递推公式:
P(n) ~= 1/2*P(n-1)
P(1) = 1
这会给我们P(n) ~= 2^-n
,这对于合理的n
来说是不太可能的。
注意,1/2只是一个粗略的估计(当n->infinity
时是正确的),概率实际上有点高,但它在-n
中仍然是指数 - 这使得它不太可能对于合理尺寸的图表。