如果我们的目标时间复杂度是O(| V | * | E |)或O(V ^ 3)等,则该问题具有简单的解决方案。但是,我的教授最近给了我们一个问题陈述的任务:
设G =(V,E)是连通的无向图。编写一个算法,确定G是否包含O(| V | + | E |)中的三角形。
此时,我很难过。 Wikipedia说:
可以测试m边的图是否在时间O(m ^ 1.41)内没有三角形。
除了在Quantum计算机上运行的算法之外,没有提到更快算法的可能性。之后我开始诉诸更好的消息来源。关于Math.SE的一个问题将我与this paper联系起来说:
已知用于查找和计数三角形的最快算法依赖于快速矩阵乘积并且具有O(n ^ω)时间复杂度,其中ω<1。 2.376是快速矩阵乘积指数。
这就是我开始意识到的可能,我们正被欺骗处理未解决的问题!那个卑鄙的教授!
然而,我仍然有点怀疑。该文件称“寻找和计算”。这相当于我试图解决的问题吗?
TL; DR:我被愚弄了,还是我忽略了一些如此微不足道的事情?答案 0 :(得分:7)
嗯,事实证明,这在O(| V | + | E |)中实际上是不可行的。或者至少,我们不知道。我读了4篇论文来达到这个结果。我在其中一个中途停了下来,因为我意识到它更关注分布式计算而不是图论。其中一个甚至提供了概率算法来确定“几乎线性”时间内的三角形自由度。三篇相关论文是:
我为该作业写了大约2页的LaTeX,引用了适当引用的论文。论文中的相关陈述是装箱:
最后,我和我的教授交谈,事实证明,这实际上是一个意想不到的可怕错误。然后他将所需的复杂度更改为O(| V | * | E |)。我不怪他,他让我学习更多的图论!
答案 1 :(得分:1)
这是O(| E | * | V |)版本的代码。
约束| V |时位掩码交叉 - 任何操作实际上是O(1),它会得到O(| E |),但那是作弊。
实际上,复杂度是O(| E | *(| V | / C))其中C是一些特定于体系结构的常量(即:32,64,128)。
function hasTriangle(v, e) {
if(v.length > 32) throw Error("|V| too big, we can't pretend bit mask intersection is O(1) if |V| is too big!");
// setup search Array
var search = new Uint32Array(v.length);
// loop through edges O(|E|)
var lastEdge = [-1, -1];
for(var i=0, l=e.length; i < l; i++) {
var edge = e[i];
if(edge[0] == lastEdge[0]) {
search[lastEdge[1]] = search[lastEdge[1]] | (1 << edge[0]);
search[edge[1]] = search[edge[1]] | (1 << edge[0]);
} else {
lastEdge = edge;
}
// bit mask intersection-any O(1), but unfortunately considered O(|V|)
if( (search[edge[0]] & search[edge[1]]) > 0 ) {
return true;
}
}
return false;
}
var V = [0, 1, 2, 3, 4, 5];
var E_no_triangle = [[0, 4], [0, 5], [1, 2], [1, 3], [2, 5]];
var E_triangle = [[0, 1], [0, 2], [0, 3], [1, 4], [2, 1], [2, 3], [4, 5]]; // Triange(0, 2, 3)
console.log(hasTriangle(V, E_no_triangle)); // false
console.log(hasTriangle(V, E_triangle)); // true