我有一个带有起始节点S和结束节点E的图G.这个图的特殊之处在于,它不是具有成本的边,而是具有成本的节点。我想找到S和E之间的方式(一组节点,W),以便最小化(W)。 (实际上,我对W不感兴趣,只是max(W))同样,如果我删除所有节点大于k的节点,那么最小的k是什么,以便S和E仍然连接?
我有一个想法,但想知道它是否正确和最佳。这是我目前的伪代码:
L := Priority Queue of nodes (minimum on top)
L.add(S, S.weight)
while (!L.empty) {
X = L.poll()
return X.weight if (X == G)
mark X visited
foreach (unvisited neighbour N of X, N not in L) {
N.weight = max(N.weight, X.weight)
L.add(N, N.weight)
}
}
我认为最坏的情况是O(n log n),其中n是节点数。
以下是我的具体问题(渗透)的一些细节,但我也对这个问题的算法感兴趣。节点权重在0和给定的最大值之间随机均匀分布。我的节点是在R²平面上的泊松分布,如果两个节点之间的距离小于给定的常数,则存在两个节点之间的边。可能有很多节点,因此它们是动态生成的(隐藏在伪代码中的foreach中)。我的起始节点在(0,0)中,结束节点是距离(0,0)大于R的距离上的任何节点。
编辑:节点上的权重是浮点数。
答案 0 :(得分:4)
从空图开始,您可以使用fast union/find data structure来增加权重顺序,一次一个地插入顶点(及其边到现有邻居),以维护连接组件集。这与构建最小生成树的Kruskal algorithm类似,但是对于您处理的每个顶点v,不是一次添加一个边,而是组合v&的所有的组件。 #39;的邻居。
您还可以跟踪哪两个组件包含起点和终点顶点。 (最初comp(S)= S和comp(E)= E;在每个并集操作之前,可以检查两个输入分量X和Y,以查看其中一个是comp(S)还是comp(E),并且后者在O(1)时间内相应地更新。)一旦这两个分量成为单个分量(即comp(S)= comp(E)),就停止。刚刚添加的顶点是S和E之间路径上的最大权重顶点,它最小化了任何顶点的最大权重。
[编辑:添加时间复杂度信息]
如果图形包含n个顶点和m个边,则按权重对顶点进行排序需要O(n log n)时间。最多将有m个联合操作(因为每个边缘都可以用来组合两个组件)。如果使用简单的不相交集合数据结构,则所有这些并集操作都可以在O(m + n log n)时间内完成,这将成为整体时间复杂度;如果还使用路径压缩,则会降低到O(m A(n)),其中A(n)是非常缓慢增长的逆Ackermann函数,但总体时间复杂度与之前保持不变,因为初始排序占主导地位。
假设整数权重,Pham Trung的二分搜索方法将采用O((n + m)log maxW)时间,其中maxW是图中最重的顶点。在稀疏图上(其中m = O(n)),这变为O(n log maxW),而我的变为O(n log n),因此如果log(maxW)<< log(n)(即,如果所有权重都非常小)。如果在具有大权重但只有少量不同权重的图上调用他的算法,那么一种可能的优化方法是在O(n log n)时间内对权重进行排序,然后将它们全部替换掉他们的排名按排序顺序排列。
答案 1 :(得分:3)
使用二进制搜索可以解决此问题。
假设解决方案是x
,从一开始,我们将使用BFS或DFS来发现图,只访问那些权重为< = x
的节点。因此,最后,如果连接了Start和End,x
可以成为解决方案。我们可以通过应用二进制搜索找到x
的最佳值。
伪代码
int min = min_value_of_all_node;
int max = max_value_of_all_node;
int result = max;
while(min<= max){
int mid = (min + max)>>1;
if(BFS(mid)){//Using Breadth first search to discover the graph.
result = min(mid, result);
max = mid - 1;
}else{
min = mid + 1;
}
}
print result;
注意:我们只需要应用图中存在的权重,这样可以帮助将二进制搜索的时间复杂度降低到O(log n),其中n是不同权重的数量
如果权重是浮动的,只需使用以下方法:
List<Double> listWeight ;//Sorted list of weights
int min = 0;
int max = listWeight.size() - 1;
int result = max;
while(min<= max){
int mid = (min + max)>>1;
if(BFS(listWeight.get(mid))){//Using Breadth first search to discover the graph.
result = min(mid, result);
max = mid - 1;
}else{
min = mid + 1;
}
}
print listWeight.get(result);