确定图形是否包含三角形?

Determine if a graph contains a triangle?

如果我们的目标时间复杂度是O(|V| * |E|) 或O(V^3) 等,这个问题很容易解决。然而,我的教授最近给了我们一个作业,问题陈述是:

Let G = (V, E) be a connected undirected graph. Write an algorithm that determines if G contains a triangle in O(|V| + |E|).

在这一点上,我被难住了。 Wikipedia 说:

It is possible to test whether a graph with m edges is triangle-free in time O(m^1.41).

除了在 Quantum 计算机上运行的算法之外,没有提到更快算法的可能性。之后我开始求助于更好的资源。 Math.SE 上的一个问题将我链接到 this paper,上面写着:

The fastest algorithm known for finding and counting triangles relies on fast matrix product and has an O(n^ω) time complexity, where ω < 2.376 is the fast matrix product exponent.

这就是我开始意识到的地方,也许我们被骗去解决一个未解决的问题!那个臭教授!

不过,我还是有点怀疑。论文说 "finding and counting"。这是否等同于我要解决的问题?

TL;DR:我是被愚弄了,还是我忽略了如此微不足道的事情?

这是 O(|E|*|V|) 版本的代码。

当你限制|V|位掩码 intersect-any 操作实际上是 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

嗯,事实证明,这在 O(|V| + |E|) 中确实不可行。或者至少,我们不知道。我读了 4 篇论文才得出这个结果。我中途停了下来,因为我意识到它更侧重于分布式计算而不是图论。其中之一甚至给出了概率算法来确定 "almost linear" 时间内的三角形自由度。三篇相关论文是:

我为作业写了大约 2 页的 LaTeX,引用了论文并附有适当的引文。论文中的相关说法加框:



最后,我和我的教授谈过,事实证明,这实际上是一个无意的严重错误。然后他将所需的复杂度更改为 O(|V| * |E|)。我不怪他,他让我学了更多图论!