Algorithm 补图算法中的最短路径
我今天参加了一个测试(数据结构课程),其中一个问题是: 给定一个无向非加权图G=(V,E),您需要编写一个算法,对于给定的节点s,返回从s到补码图中所有节点V'的最短路径 补码图G'=(E',V')包含G中不共享边且仅共享边的任何to节点之间的边 该算法需要在(原始图的)O(V+E)中运行 我问了50个不同的学生,他们中甚至没有一个正确地解决了这个问题 有什么想法吗? 谢谢,Algorithm 补图算法中的最短路径,algorithm,data-structures,big-o,graph-theory,breadth-first-search,Algorithm,Data Structures,Big O,Graph Theory,Breadth First Search,我今天参加了一个测试(数据结构课程),其中一个问题是: 给定一个无向非加权图G=(V,E),您需要编写一个算法,对于给定的节点s,返回从s到补码图中所有节点V'的最短路径 补码图G'=(E',V')包含G中不共享边且仅共享边的任何to节点之间的边 该算法需要在(原始图的)O(V+E)中运行 我问了50个不同的学生,他们中甚至没有一个正确地解决了这个问题 有什么想法吗? 谢谢, 巴拉克。课程工作人员已经公布了考试的正式答案 答案是: “该算法基于BFS,并进行了一些调整。 对于图中的每个节点,我们
巴拉克。课程工作人员已经公布了考试的正式答案 答案是: “该算法基于BFS,并进行了一些调整。 对于图中的每个节点,我们将添加两个字段-next和prev。使用这两个字段,我们可以维护两个节点的双链接列表:L1、L2。 在算法的每次迭代开始时,L1在图中具有所有while节点,L2为空。 BFS代码(无初始化)为: 在第3-5行的循环结束处,L1包含G中与u不相邻的所有白色节点,或者换句话说,在补码图中与u相邻的所有白色节点。 因此,算法的运行时间等于补图上原始BFS的运行时间。 时间是O(V+E),因为第4-5行最多执行2E次,第7-9行最多执行V次(每个节点只能从L1中退出一次)。” 注意:这是从希伯来语翻译过来的原始解决方案 我希望你觉得这对我很有帮助,谢谢大家帮助我
巴拉克。我想提出一种不同的方法 初始化:-
未发现的,并用所有节点初始化它
当前节点
=出列(队列)补边
)。这可以通过循环所有
未发现中的节点并检查其是否连接到
当前节点
补足\u边中的每个节点
执行3
操作
- 如果最佳,则更新距离
- 从未发现节点中删除此节点
- 排队(队列,此节点)
未发现的
将很快变为空。
在实现过程中,使用哈希将边存储在图形中,这将加快步骤2
以下是示例代码:-
HashSet<Integer> adjList[]; // graph stored as adjancency list
public int[] calc_distance(int start){
HashSet<Integer> undiscovered = new HashSet<>();
for(int i=1;i<=N;i++){
undiscovered.add(i);
}
int[] dist = new int[N+1];
Arrays.fill(dist, Integer.MAX_VALUE/4);
Queue<Integer> q = new LinkedList<>();
q.add(start);
dist[start] = 0;
while(!q.isEmpty() && undiscovered.size()>0){
int curr = q.poll();
LinkedList<Integer> complement_edges = new LinkedList<>();
for(int child : undiscovered){
if(!adjList[curr].contains(child)){
// curr and child is connected in complement
complement_edges.add(child);
}
}
for(int child : complement_edges){
if(dist[child]>(dist[curr]+1)){
dist[child] = dist[curr]+1;
}
// remove complement_edges from undiscovered
undiscovered.remove(child);
q.add(child);
}
}
return dist;
}
}
HashSet adjList[];//存储为邻接列表的图形
公共整数[]计算距离(整数起点){
HashSet unfounded=新HashSet();
对于(int i=1;i0){
int curr=q.poll();
LinkedList补码_边=新LinkedList();
for(int子项:未发现){
如果(!adjList[curr].包含(子项)){
//curr和child在补语中连接
补充_边。添加(子项);
}
}
for(整数子级:补边){
如果(区[子]>(区[当前]+1)){
dist[child]=dist[curr]+1;
}
//从未发现的边上删除补边
未被发现。移除(儿童);
q、 添加(儿童);
}
}
返回距离;
}
}
Hi,你可以肯定我在考试期间用了两个小时的大脑,之后又用了四个小时。这不是家庭作业,只是纯粹的好奇心。我同意Okuma的观点,你的问题更适合不同的堆栈交换站点。我推荐:你确定它应该是原始图的O(V+E)吗?你可以有一个非常稀疏的图,它会产生一个超密的补码,其中O(V'+E')会比O(V+E)大。是的,@miky,我敢肯定。对于O(V'+E'),它非常简单。我假设图是作为邻接列表给出的,否则你总是需要O(V^2),在这种情况下,证明O(V'+E')在O(V+E)中非常简单。如果图形以邻接列表的形式给出,那么证明O(V'+E')在O(V+E)中就有点困难了。@Miky Dinescu-正如你所要求的那样。非常感谢。谢谢你的回答,这对我帮助很大!