我找到了一个有向图的函数,对于它中的顶点'u'和'v',它计算从'u'到'v'的所有可能的步行,其中在步行中具有正好k个边缘。 代码和算法来自here。所以,
// C++ program to count walks from u to v with exactly k edges
#include <iostream>
using namespace std;
// Number of vertices in the graph
#define V 4
// A naive recursive function to count walks from u to v with k edges
int countwalks(int graph[][V], int u, int v, int k)
{
// Base cases
if (k == 0 && u == v) return 1;
if (k == 1 && graph[u][v]) return 1;
if (k <= 0) return 0;
// Initialize result
int count = 0;
// Go to all adjacents of u and recur
for (int i = 0; i < V; i++)
if (graph[u][i]) // Check if is adjacent of u
count += countwalks(graph, i, v, k-1);
return count;
}
我试图找到并证明这种算法的复杂性。根据帖子:
“上述函数的最坏情况时间复杂度为O(V ^ k),其中V 是给定图形中的顶点数。我们可以简单地分析 绘制递归树的时间复杂度。最坏的情况发生在 完整的图表。在最坏的情况下,递归树的每个内部节点 肯定会有n个孩子。“
但是,我无法找到导致我可以分析的树的递归,以证明此算法是O(V^k)
。另外,我认为最好的情况是Theta(1)
。真的吗?平均情况怎么样?
答案 0 :(得分:1)
对于完整的图表,每个节点都连接到其他节点,因此for
循环将进行|V|
递归调用。这将在每次递归调用时发生,直到k
变为1,因此总共O(|V|^k)
次递归调用。
你可以这样表达:
T(V, k) = |V|*T(V, k - 1)
= |V|*|V|*T(V, k - 2)
= |V|^2*|V|*T(V, k - 3)
= ...
始终为T(V, _)
,因为可以多次访问节点。
最好的情况确实是O(1)
,当前三个条件中的一个条件在第一次通话期间触发时。{/ p>
我不确定的平均情况,但我认为它应该仍然很糟糕。考虑链接列表图和巨大的k
:您将多次移动相同的边缘以使k
为0或1.随着您添加更多路径,这会逐渐变得更糟。
答案 1 :(得分:0)
通用的“平均情况”分析在这样的问题中有点不适应,因为您可以选择如何定义“随机”图形。一种方式是说每个可能的边缘以0 <= p <= 1的概率p出现,然后尝试用p来分析平均情况运行时间。但是还有其他方法来定义随机图。平均案例分析通常很难。但是,如果你用“平均”来定义你的意思(即它是什么意思是随机图)那么有人可能会对它进行刺激。