Matrix 用O(N)中的邻接矩阵求有序图的根顶点

Matrix 用O(N)中的邻接矩阵求有序图的根顶点,matrix,graph-algorithm,Matrix,Graph Algorithm,我有一个A的邻接矩阵,我需要找到所有其他顶点都有边的顶点(在它的行中,除了对角线之外,所有的1): 如果这是邻接矩阵: 0 0 0 0 0 0 1 1 0 该算法应产生顶点3 假设至少有一个这样的顶点 O(N^2)(N是顶点数)中的解很简单,但如何在O(N)中实现这一点呢?先决条件: 这张图是一张图表 有一个顶点,所有其他顶点都有一个入边 由于边需要诱导一个总的排序,需要找到的顶点是“最小”的顶点,它没有任何外边,因为这将是它已经连接到的其他边之一,这将导致一个循环,这在有序图中是不允许的

我有一个A的邻接矩阵,我需要找到所有其他顶点都有边的顶点(在它的行中,除了对角线之外,所有的1):

如果这是邻接矩阵:

0 0 0
0 0 0
1 1 0
该算法应产生顶点3

假设至少有一个这样的顶点

O(N^2)(N是顶点数)中的解很简单,但如何在O(N)中实现这一点呢?

先决条件:

  • 这张图是一张图表
  • 有一个顶点,所有其他顶点都有一个入边
由于边需要诱导一个总的排序,需要找到的顶点是“最小”的顶点,它没有任何外边,因为这将是它已经连接到的其他边之一,这将导致一个循环,这在有序图中是不允许的

此外,图形需要连接,因此所有路径都需要指向最小顶点,这就引出了该算法:

  • 从可能的候选行集合开始
  • 从集合中选择一个顶点,并在可能的边上迭代到其余候选顶点。
    • 如果候选项存在优势,则从列表中删除步骤2中的候选项,并在第2步继续使用新候选项
    • 如果该顶点没有边,则从候选集中删除目标候选,然后继续下一条可能的边
    • 如果没有留下候选顶点,则当前顶点就是您要查找的顶点

  • 由于每个步骤可以在O(1)中执行,并且在每个步骤中剩余候选集减少,因此运行时间应为O(N)

    有序图是在其顶点上具有总顺序的图。没有其他要求,特别是,它不限制边缘可以到达的位置。因此,问题的答案是,有时你不能做得比O(n ^ 2)更好:考虑一个邻接矩阵,其中一行具有所有非对角线条目等于1,并且所有其他行都有10个非对角线条目。除非你非常幸运,否则你需要遍历几乎整个邻接矩阵来找出哪一行没有非对角零

    所以我假设你是指一个有向图,它允许一个。即a(DAG)。在这种情况下,塞巴斯蒂安已经回答了这个问题,但是由于这个问题的答案没有被接受,让我试着解释清楚

    如果DAG中的顶点具有来自其他顶点的传入边,则它没有传出边,因为这些边将形成长度为2的循环。换句话说,它对应的列只有零。这样一个顶点称为通用sink,有一个著名的O(N)算法来找到它

    通用算法:

  • 候选:={0,1,…,N-1}
  • 而|候选人|>1则会:
    • 任意选择候选u和v
    • 如果(u,v)是边,则从坐标系中删除u,否则从候选坐标系中删除v
  • 测试最后剩余的候选项是否为通用接收器
  • 如果您知道图形具有通用接收器,那么最后一步是不必要的

    while循环的迭代次数为N-1,因为每次迭代都会从候选集合中删除一个顶点。该算法是正确的,因为它只删除不能作为通用汇的顶点-删除的顶点具有传出边或没有来自某个顶点的传入边

    在下面的代码中,您可以注意到我们并没有明确地保留候选列表。for循环的步骤i中的候选列表是{candidate,i,i+1,…,N-1},并且所选候选u和v是候选和i

    //步骤2
    int候选者=0;
    
    对于(int i=1;我已经在内存中加载了数据,我知道这应该是可能的,只是不知道怎么做我在谷歌上搜索了一下,但没有发现任何有用的东西,我也无法在我的一个上弥补任何东西,这就是我写在这里的原因。我刚刚看到你说这是一个“。这使得矩阵“特别”-如果你发现了,它有什么特别之处,你将看到如何“穿越”我不太理解这个问题。例如,你可以有10个链接的顶点。在这种情况下,没有其他所有顶点都有边的顶点。你对这个矩阵有一些特殊的约束吗?是的,我可以假设至少有一个这样的顶点有所有顶点的边其他的。
    // 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);