如何在线性时间内找到超级巨星?


28

考虑有向图。当且仅当无法从该节点到达其他节点,但所有其他节点都具有的边缘时,我们才称该节点为超级星。正式地:vv v

v superstar :⟺outdeg(v)=0indeg(v)=n1

其中n为图中的节点数。例如,在下图中,未填充的节点是超级明星(其他节点不是)。

超级巨星
[ 来源 ]

您如何在O(n)时间中识别有向图中的所有超级明星?可以从通常的候选项中选择合适的图形表示形式;请不要使用将问题的复杂性转移到预处理的表示形式。

无法做出有关密度的假设。我们不认为图表包含超级巨星;如果没有,则算法应识别出它。

符号outdeg是一个节点的传出边缘的数目,indeg传入边缘相似。


1
是否允许,其中k是边,还是只需要查看每个顶点上的O 1 )个边?O(n+k)kO(1)
凯文(Kevin)

@Kevin不,是一个严格的要求。关于第二个问题:我什至不知道这是否必要,但您当然不能做更多。O(n)
拉斐尔

你知道答案吗?可以在吗?O(n)
戴夫·克拉克2012年

@DaveClarke:是的,是的。
拉斐尔

您应该进一步限制表示形式;对于邻接表,不可能使用线性算法(只是为了确认顶点是超级星,您可能需要遍历每个顶点的整个列表)。
吉尔斯(Gilles)'“ SO-不要邪恶”

Answers:


18

我们可以通过检查边的存在来消除除一个顶点以外的所有顶点,因为我们可以为所检查的每个边消除一个可能性。特别是,如果存在从xy的边,我们将x消除,然后继续到y(因为可以从它到达另一个顶点);如果不是,我们消除y(因为无法从x到达)。一旦我们到达最后一个顶点,则应将未消除的任何一个顶点彼此进行比较(确保维持超级星的条件:有边缘进入但没有向外的边缘),直到将其消除或确认为超级星为止。一些伪代码:n1xyxyyx

vertex superstar(graph g)
    current vertex = first
    # Go through each vertex
    for each subsequent vertex in g ("next")
        # If there's an edge from this to the next, we eliminate this one [move to the new one].
        # If not, we just stay here.
        if edge exists from current to next
            candidate = next
        end if
    end for
    # Now we are on the final remaining candidate, check whether it satisfies the requirements.
    # just a rename for clarity
    candidate = current
    for each other vertex in g
        if edge from current to other exists
            return null 
        else if no edge from other to current
            return null
        end if
    end for
    return candidate
end superstar

让我们通过一个例子来说明该方法。选取此数组,源顶点在顶部,目标顶点在侧面。1表示边缘:

12341101210131114110

我将把我们排除为潜在超级明星的顶点显示为灰色。我将使用绿色和红色指示当它们出现时要查看的边缘,而不包含我们正在寻找的边缘,使用蓝色指示我们已经查看过的边缘。

我们先看一下顶点1和2。

12341101210131114110

12341101210131114110

我们看到没有这样的边,因此我们消除1并将3作为我们的当前顶点。回想一下,我们已经消除了2个,所以看看是否有4到3的边:

12341101210131114110

从4到3有一条边,因此我们消除了4。在这一点上,我们已经消除了除顶点(3)之外的所有顶点,因此请检查其边并查看其是否合格:

12341101210131114110

从1到3有一条边,但没有相反的边,因此3仍然是候选者。

12341101210131114110

还有一个从2到3的边,但不是相反的,因此3仍然是候选。

12341101210131114110

从4到3有一条边,但从3到4没有一条边。完成了我们对3的边的检查,我们发现它实际上是超级巨星。

n1nnn12×(n1)3n3O(n)Θ(n)


8

这不是名人问题吗?

如果只有一位超级明星(名人)。

A[i,j]=1ij0

A[i,j]O(1)A[i,j]=1iA[i,j]=0j

维护一份当前候选人名单,一一淘汰。链表就足够了。

最后,您可以验证您的候选人是否确实是超级巨星。

O(n)


(i,j)

3
@Raphael:只需从链接列表中选择前两个候选人。(head和head-> next)。
Aryabhata'3

6

该答案解决了可能使用任何图形表示形式的问题版本,而不是问题的当前版本。

  • 将图形存储为一对邻接列表和反向邻接列表,其中每个列表还包含列表的长度,因此分别包含边缘数和边缘数。

  • O(|E|)

  • 0n1O(|N|)


好的,我看到允许任何图形表示都太弱了。我将问题限制在我的意图范围内。
拉斐尔

2

仅供参考,这是Kevin发表的内容的递归版本的伪代码。

superstar(V, E) {
  if ( |V| == 1 ) {
    return V.pop
  }

  a = V.pop
  b = V.pop
  if ( (a,b) ∈ E ) {
    no_ss = a
    keep  = b
  }
  else {
    no_ss = b
    keep = a
  }

  s = superstar(V ++ keep)

  return ( s != null && (no_ss, s) ∈ E && !(s, no_ss) ∈ E ) ? s : null
}

hasSuperstar(V, E) = superstar(V, E) != null
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.