考虑有向图。当且仅当无法从该节点到达其他节点,但所有其他节点都具有的边缘时,我们才称该节点为超级星。正式地:v
v
其中为图中的节点数。例如,在下图中,未填充的节点是超级明星(其他节点不是)。
[ 来源 ]
您如何在时间中识别有向图中的所有超级明星?可以从通常的候选项中选择合适的图形表示形式;请不要使用将问题的复杂性转移到预处理的表示形式。
无法做出有关密度的假设。我们不认为图表包含超级巨星;如果没有,则算法应识别出它。
符号:是一个节点的传出边缘的数目,传入边缘相似。
考虑有向图。当且仅当无法从该节点到达其他节点,但所有其他节点都具有的边缘时,我们才称该节点为超级星。正式地:v
v
其中为图中的节点数。例如,在下图中,未填充的节点是超级明星(其他节点不是)。
[ 来源 ]
您如何在时间中识别有向图中的所有超级明星?可以从通常的候选项中选择合适的图形表示形式;请不要使用将问题的复杂性转移到预处理的表示形式。
无法做出有关密度的假设。我们不认为图表包含超级巨星;如果没有,则算法应识别出它。
符号:是一个节点的传出边缘的数目,传入边缘相似。
Answers:
我们可以通过检查边的存在来消除除一个顶点以外的所有顶点,因为我们可以为所检查的每个边消除一个可能性。特别是,如果存在从x到y的边,我们将x消除,然后继续到y(因为可以从它到达另一个顶点);如果不是,我们消除y(因为无法从x到达)。一旦我们到达最后一个顶点,则应将未消除的任何一个顶点彼此进行比较(确保维持超级星的条件:有边缘进入但没有向外的边缘),直到将其消除或确认为超级星为止。一些伪代码:
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表示边缘:
我将把我们排除为潜在超级明星的顶点显示为灰色。我将使用绿色和红色指示当它们出现时要查看的边缘,而不包含我们正在寻找的边缘,使用蓝色指示我们已经查看过的边缘。
我们先看一下顶点1和2。
我们看到没有这样的边,因此我们消除1并将3作为我们的当前顶点。回想一下,我们已经消除了2个,所以看看是否有4到3的边:
从4到3有一条边,因此我们消除了4。在这一点上,我们已经消除了除顶点(3)之外的所有顶点,因此请检查其边并查看其是否合格:
从1到3有一条边,但没有相反的边,因此3仍然是候选者。
还有一个从2到3的边,但不是相反的,因此3仍然是候选。
从4到3有一条边,但从3到4没有一条边。完成了我们对3的边的检查,我们发现它实际上是超级巨星。
仅供参考,这是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