图论:广度优先搜索

Graph theory: Breadth First Search

本文关键字:广度优先搜索 图论      更新时间:2023-10-16

有n个顶点由m条边连接。有些顶点是特殊的,而另一些则是普通的。从一个顶点移动到另一个顶点,几乎有一条路径。

首次查询:我需要找出存在多少对直接或间接连接的特殊顶点。

我的方法:我将应用BFS(通过队列)来查看有多少节点以某种方式相互连接。让我在其中发现的特殊顶点的数量为n,那么我的查询答案将为nC2。我将重复此操作,直到访问所有顶点为止。

第二次查询:路径上任意两个特殊顶点之间的顶点数。

我的方法:在查询1的方法中,我将应用BFS找出任意两个特殊顶点之间的路径,然后回溯并标记位于路径上的顶点。

问题:顶点的数量可以高达50000。所以,应用BFS,然后我想,对于我的时间限制(2秒),回溯会更慢。

我有所有顶点的列表和它们的邻接列表。现在,当BFS时在我的队列中推送顶点时,我能以某种方式计算查询2的答案吗?有没有更好的方法可以用来解决这个问题?输入格式是这样的,我会被一个接一个地告知一个顶点是否特殊,然后我会得到关于连接两个顶点的路径的信息。从一个顶点移动到另一个顶点,几乎有一条路径。

第一个查询是通过将林拆分为树来解决的。

从完整的顶点集开始,选择一个顶点,然后从那里访问您可以访问的每个节点,直到您无法访问任何其他顶点为止。这是一棵树。对每棵树重复上述步骤。

现在有K个顶点包,每个顶点包包含0-j个特殊的顶点。这回答了第一个问题。

对于第二个问题,我假设一个平凡的解决方案确实是对其子图中的每一对的顶点到另一个顶点之间的路径进行BFS。

您还可以利用子图的树特性。这个问题:如何在线性时间内找到树中最短的简单路径?提到它。(不过,我还没有真正深入研究)

对于第一个查询,一轮BFS和您所描述的一些简单计算是最优的。

对于第二个查询,假设最坏的情况是所有顶点都是特殊的,并且图是一棵树,每个查询进行BFS将给出O(Q|V|)的复杂性,其中Q是查询的数量。如果Q大于104并且|V|也大于104,那么您将遇到麻烦。

在最坏的情况下,我们基本上是在树/森林上解决所有对的最短路径问题。当|V|很小时,我们可以在所有节点上进行BFS,这导致了O(|V|2)算法。然而,有一种更快的算法:

  • 读取所有第二类查询并将所有对存储在集合S中
  • 对于森林中的每棵树:
    • 为当前树选择一个根节点。计算从根节点到当前树中所有其他节点的距离(无论它是否特殊)
    • 计算被查询的所有节点对(存储在集合S中)的最低公共祖先(LCA)。这可以通过Tarjan的离线LCA算法来实现
    • 通过以下公式计算一对节点之间的距离:dist(root, a) + dist(root, b) - dist(root, lca(a,b))

设arr为布尔数组,其中arr[i]如果是特殊的,则为1,否则为0。find-set(i)返回树的根节点。因此,位于同一棵树中的任何节点都返回相同的数字。

for(int i=1; i<n; i++){ 
for(int j=i+1; j<=n; j++){
if(arr[i]==1 && arr[j]==1){        //If both are special
if(find-set(i)==find-set(j)){  //and both i and j belong to the same tree
//k++ where k is answer to the first query.
//bfs(i,j) and find the intermediate vertices and do ver[i]=1 for the corresponding intermediate vertex/node.
}
}
}        
}

最后计算ver矩阵中1的no,这是第二个查询的答案。