[英]Find the shortest cycle in a positive weighted directed graph passing through only specific nodes (not the other nodes)
考虑一个加权有向图,包括 V 个顶点和 E 个边。 我正在寻找一种算法,找到仅通过 S 某个节点(必须通过 S 中的所有节点)而不是其他节点的最短循环。 循环从集合 S 中的节点 w 开始和结束。
是否可以删除 V - S 集合中的节点并删除它们对应的连接边,然后将算法(用于寻找最短循环)应用于此图,仅包括 S 节点及其对应的边?
我强调我们只考虑集合 S 中的节点,而不考虑其他节点。
我不确定以下链接是否与我的问题相关。 该链接要求必须通过蓝色节点的最短循环,但该循环可能会通过黑色节点(对此我不确定)。
是的,按照您的问题陈述方式,考虑方法是正确的。
删除所有不属于集合 S 的顶点的图称为导出子图。 原始图中仅使用 S 中的顶点的每个路径/循环也可以在导出子图中找到。 因此,在导出子图中寻找最短环等同于在原始图中寻找环。
如果您的问题需要找到使用 S 中所有节点的最短循环,那么您正在解决旅行商问题,该问题被称为 NP-hard,这意味着没有已知的(并且可能不存在)多项式算法。 也就是说,这是一个经过充分研究的问题,您可以从精确算法(如果集合足够小)和启发式/近似算法中进行选择,以适应更大的规模。
第一步是检测图表中存在的循环(如果有)
这可以通过修改深度优先搜索 (DFS) 来完成,如下所示:
- As the DFS proceeds through nodes, store the predecessor of each node visited
- IF a node is visited for the second time ( indicating cycle )
- Back track through the node predeccessors, storing the reversed cycle
现在您可以过滤为您的条件检测到的周期(访问 S 中的节点、最短等)
这是检测和记录周期的 DFS 的 C++ 代码
void cGraph::dfs_cycle_detector(vertex_t start)
{
std::vector<bool> visited(vVertex.size(), false);
vVertex_t pred(vVertex.size(), 0);
std::stack<vertex_t> wait;
wait.push(start);
while (!wait.empty())
{
vertex_t v = wait.top();
wait.pop();
int vi = findIndex(v);
if (!visited[vi])
{
visited[vi] = true;
for (vertex_t w : adjacentOut(v))
{
if (!visited[findIndex(w)])
{
wait.push(w);
pred[findIndex(w)] = v;
}
else
{
// previously visited node - a cycle
vVertex_t cycle;
cycle.push_back(w);
cycle.push_back(v);
vertex_t pv = pred[findIndex(v)];
cycle.push_back(pv);
while (pv != w)
{
// back track one hop
pv = pred[findIndex(pv)];
cycle.push_back(pv);
}
std::reverse(cycle.begin(), cycle.end());
// display cycle
std::cout << "cycle: ";
for (vertex_t vc : cycle)
std::cout << vc->userName() << " ";
std::cout << "\n";
}
}
}
}
}
完整的应用程序位于https://github.com/JamesBremner/graphCycler
示例 output:
node a linked to b x
node b linked to c
node c linked to d
node d linked to a
node x linked to y
node y linked to
cycle: a b c d a
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.