我有一个ordered graph的邻接矩阵,我需要找到所有其他边缘到的顶点(在它的行中除了对角线之外都有1个):
如果这是邻接矩阵:
0 0 0
0 0 0
1 1 0
算法应该产生顶点3。
假设至少有一个这样的顶点。
O(N ^ 2)中的解(N是顶点数)是微不足道的,但如何在O(N)中完成?
答案 0 :(得分:2)
前提条件:
由于边缘需要引入总排序,所以需要找到的顶点是“最小”顶点,它没有任何外边缘,因为这将是它已连接的其他边之一to会导致一个循环,这在一个有序图中是不允许的。
此外,图形需要连接,因此所有路径都需要通向最小的顶点,这使我们得到了这个算法:
由于每个步骤都可以在O(1)中执行,并且在每个步骤中减少剩余候选者的集合,因此运行时间应该是O(N)。
答案 1 :(得分:0)
有序图是在其顶点上具有总次序的图。没有其他要求,特别是它不限制边缘可以去的地方。所以这个问题的答案是你有时候不能做得比O(N ^ 2)更好:考虑一个邻接矩阵,其中一行所有非对角线条目等于一,而所有其他行都有一个零非对角线条目。除非你非常幸运,否则你需要通过几乎整个邻接矩阵找出哪一行没有非对角线零。
因此,我认为您的意思是指向允许 topological ordering 的有向图。也就是说,directed acyclic graph(DAG)。在那种情况下,塞巴斯蒂安已经回答了,但由于答案未被接受,让我试着更清楚地解释它。
如果DAG中的顶点具有来自每个其他顶点的入射边,则它没有外出边,因为它们将形成长度为2的循环。换句话说,其对应列仅具有零。这样的顶点称为通用接收器,并且有一种众所周知的O(N)算法可用于查找它。
常规算法:
如果你知道你的图表有一个通用接收器,那么最后一步是不必要的。
while循环的迭代次数为N-1,因为每次迭代都会从候选集中删除一个顶点。该算法是正确的,因为它只删除不能成为通用接收器的顶点 - 移除的顶点具有传出边缘,或者它没有来自某个顶点的传入边缘。
在下面的代码中,您可以注意到我们没有明确地保留候选人列表。 for-cycle的步骤 i 中的候选者列表是 {candidate,i,i + 1,...,N-1} 和所选候选人 u 和 v 是候选人和 i 。
// step 2
int candidate = 0;
for(int i=1; i<N; i++)
{
if(edge[candidate][i] == 1)
candidate = i;
}
// step 3
bool no_sink = false;
for(int i=0; i<N; i++)
{
if(candidate != i && (edge[candidate][i] == 1 || edge[i][candidate]==0))
no_sink = true;
}
if(no_sink)
printf("No universal sink.");
else
printf("The universal sink is %d.", candidate);